{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Time Series Classification, Regression, Clustering & More"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Overview of this notebook\n",
    "\n",
    "* Introduction to time series classification, regression, clustering\n",
    "* `sktime` data format fo \"time series panels\" = collections of time series\n",
    "* Basic vignettes for TSC, TSR, TSCl\n",
    "* Advanced vignettes - pipelines, ensembles, tuning"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "Deal with *collections of time series* = \"panel data\"\n",
    "\n",
    "Classification = try to assign one *category* per time series, after training on time series/category examples\n",
    "\n",
    "- Example: Daily energy consumption profile over time - Predict season, e.g., winter/summer, or type of consumer\n",
    "\n",
    "Regression = try to assign one continuous *numerical value* per time series, after training on time series/category examples\n",
    "\n",
    "- Example: Temperature/pressure/time profile of chemical reactor - Predict total purity (fraction of 1)\n",
    "\n",
    "Clustering = put different time series in a small number of similarity buckets\n",
    "\n",
    "- Example: Service Level Agreement (SLA) Breaches - Group the collected Panel data to identify common reasons for SLA failures"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Time Series Classification:\n",
    "\n",
    "<img src=\"./img/tsc.png\" width=\"600\" alt=\"time series classification\"> [<i>&#x200B;</i>](./img/tsc.png)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import pandas as pd\n",
    "\n",
    "# Increase display width\n",
    "pd.set_option(\"display.width\", 1000)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2.1 Panel data - `sktime` data formats <a name=\"panel\"></a>\n",
    "\n",
    "`Panel` is an abstract data type where the values are observed for:\n",
    "\n",
    "* `instance`, e.g., patient\n",
    "* `variable`, e.g., blood pressure, body temperature of the patient\n",
    "* `time`/`index`, e.g., January 12, 2023 (usually but not necessarily a time index!)\n",
    "\n",
    "One value X is: \"patient 'A' had blood pressure 'X' on January 12, 2023\"\n",
    "\n",
    "Time series classification, regression, clustering: slices `Panel` data by instance"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "Preferred format 1: `pd.DataFrame` with 2-level `MultiIndex`, (instance, time) and columns: variables\n",
    "\n",
    "Preferred format 2: 3D `np.ndarray` with index (instance, variable, time)\n",
    "\n",
    "* `sktime` supports and recognizes multiple data formats for convenience and internal use, e.g., `dask`, `xarray`\n",
    "* abstract data type = \"scitype\"; in-memory specification = \"mtype\"\n",
    "* More information in tutorial on [in-memory data representations and data loading](https://www.sktime.net/en/latest/examples/AA_datatypes_and_datasets.html#In-memory-data-representations-and-data-loading)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.1.1 Preferred format 1 - `pd-multiindex` specification"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`pd-multiindex` = `pd.DataFrame` with 2-level `MultiIndex`, (instance, time) and columns: variables"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sktime.datasets import load_italy_power_demand\n",
    "\n",
    "# load an example time series panel in pd-multiindex mtype\n",
    "X, _ = load_italy_power_demand(return_type=\"pd-multiindex\")\n",
    "\n",
    "# renaming columns for illustrative purposes\n",
    "X.columns = [\"total_power_demand\"]\n",
    "X.index.names = [\"day_ID\", \"hour_of_day\"]"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The Italy power demand dataset has:\n",
    "\n",
    "* 1096 individual time series instances = single days of total power demand (mean subtracted)\n",
    "* one single variable per time series instances, `total_power_demand`\n",
    "    * total power demand on that day, in that hourly period\n",
    "    * Since there's only one column, it is a univariate dataset\n",
    "* individual time series are observed at 24 time (period) points (the same number for all instances)\n",
    "\n",
    "In the dataset, days are jumbled and of different scope (independent sampling).\n",
    "* considered independent - because `hour_of_day` in one sample doesn't affect `hour_of_day` in another\n",
    "* for task, e.g., \"identify season or weekday/weekend from pattern\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th>total_power_demand</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>day_ID</th>\n",
       "      <th>hour_of_day</th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th rowspan=\"5\" valign=\"top\">0</th>\n",
       "      <th>0</th>\n",
       "      <td>-0.710518</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>-1.183320</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>-1.372442</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>-1.593083</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>-1.467002</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th rowspan=\"5\" valign=\"top\">1095</th>\n",
       "      <th>19</th>\n",
       "      <td>0.180490</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>20</th>\n",
       "      <td>-0.094058</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>21</th>\n",
       "      <td>0.729587</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>22</th>\n",
       "      <td>0.210995</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>23</th>\n",
       "      <td>-0.002542</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>26304 rows × 1 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "                    total_power_demand\n",
       "day_ID hour_of_day                    \n",
       "0      0                     -0.710518\n",
       "       1                     -1.183320\n",
       "       2                     -1.372442\n",
       "       3                     -1.593083\n",
       "       4                     -1.467002\n",
       "...                                ...\n",
       "1095   19                     0.180490\n",
       "       20                    -0.094058\n",
       "       21                     0.729587\n",
       "       22                     0.210995\n",
       "       23                    -0.002542\n",
       "\n",
       "[26304 rows x 1 columns]"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sktime.datasets import load_basic_motions\n",
    "\n",
    "# load an example time series panel in pd-multiindex mtype\n",
    "X, _ = load_basic_motions(return_type=\"pd-multiindex\")\n",
    "\n",
    "# renaming columns for illustrative purposes\n",
    "X.columns = [\"accel_1\", \"accel_2\", \"accel_3\", \"gyro_1\", \"gyro_2\", \"gyro_3\"]\n",
    "X.index.names = [\"trial_no\", \"timepoint\"]"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The basic motions dataset has:\n",
    "\n",
    "* 80 individual time series instances = trials = person engaging in an activity like running, badminton, etc.\n",
    "* six variables per time series instance, `dim_0` to `dim_5` (renamed according to the values they represent)\n",
    "    * 3 accelerometer and 3 gyrometer measurements\n",
    "    * hence a multivariate dataset\n",
    "* individual time series are observed at 100 time points (the same number for all instances)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th>accel_1</th>\n",
       "      <th>accel_2</th>\n",
       "      <th>accel_3</th>\n",
       "      <th>gyro_1</th>\n",
       "      <th>gyro_2</th>\n",
       "      <th>gyro_3</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>trial_no</th>\n",
       "      <th>timepoint</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th rowspan=\"5\" valign=\"top\">0</th>\n",
       "      <th>0</th>\n",
       "      <td>0.079106</td>\n",
       "      <td>0.394032</td>\n",
       "      <td>0.551444</td>\n",
       "      <td>0.351565</td>\n",
       "      <td>0.023970</td>\n",
       "      <td>0.633883</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>0.079106</td>\n",
       "      <td>0.394032</td>\n",
       "      <td>0.551444</td>\n",
       "      <td>0.351565</td>\n",
       "      <td>0.023970</td>\n",
       "      <td>0.633883</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>-0.903497</td>\n",
       "      <td>-3.666397</td>\n",
       "      <td>-0.282844</td>\n",
       "      <td>-0.095881</td>\n",
       "      <td>-0.319605</td>\n",
       "      <td>0.972131</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>1.116125</td>\n",
       "      <td>-0.656101</td>\n",
       "      <td>0.333118</td>\n",
       "      <td>1.624657</td>\n",
       "      <td>-0.569962</td>\n",
       "      <td>1.209171</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>1.638200</td>\n",
       "      <td>1.405135</td>\n",
       "      <td>0.393875</td>\n",
       "      <td>1.187864</td>\n",
       "      <td>-0.271664</td>\n",
       "      <td>1.739182</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th rowspan=\"5\" valign=\"top\">79</th>\n",
       "      <th>95</th>\n",
       "      <td>28.459024</td>\n",
       "      <td>-16.633770</td>\n",
       "      <td>3.631869</td>\n",
       "      <td>8.978229</td>\n",
       "      <td>-3.611533</td>\n",
       "      <td>-1.491489</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>96</th>\n",
       "      <td>10.260094</td>\n",
       "      <td>0.102775</td>\n",
       "      <td>1.269261</td>\n",
       "      <td>-1.645964</td>\n",
       "      <td>-3.377157</td>\n",
       "      <td>1.283746</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>97</th>\n",
       "      <td>4.316471</td>\n",
       "      <td>-3.574319</td>\n",
       "      <td>2.063831</td>\n",
       "      <td>-1.717875</td>\n",
       "      <td>-1.843054</td>\n",
       "      <td>0.484734</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>98</th>\n",
       "      <td>0.704446</td>\n",
       "      <td>-4.920444</td>\n",
       "      <td>2.851857</td>\n",
       "      <td>-2.982977</td>\n",
       "      <td>-0.809665</td>\n",
       "      <td>-0.721774</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>99</th>\n",
       "      <td>-2.074749</td>\n",
       "      <td>-6.892377</td>\n",
       "      <td>4.848379</td>\n",
       "      <td>-1.350330</td>\n",
       "      <td>-1.203844</td>\n",
       "      <td>-1.776470</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>8000 rows × 6 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "                      accel_1    accel_2   accel_3    gyro_1    gyro_2    gyro_3\n",
       "trial_no timepoint                                                              \n",
       "0        0           0.079106   0.394032  0.551444  0.351565  0.023970  0.633883\n",
       "         1           0.079106   0.394032  0.551444  0.351565  0.023970  0.633883\n",
       "         2          -0.903497  -3.666397 -0.282844 -0.095881 -0.319605  0.972131\n",
       "         3           1.116125  -0.656101  0.333118  1.624657 -0.569962  1.209171\n",
       "         4           1.638200   1.405135  0.393875  1.187864 -0.271664  1.739182\n",
       "...                       ...        ...       ...       ...       ...       ...\n",
       "79       95         28.459024 -16.633770  3.631869  8.978229 -3.611533 -1.491489\n",
       "         96         10.260094   0.102775  1.269261 -1.645964 -3.377157  1.283746\n",
       "         97          4.316471  -3.574319  2.063831 -1.717875 -1.843054  0.484734\n",
       "         98          0.704446  -4.920444  2.851857 -2.982977 -0.809665 -0.721774\n",
       "         99         -2.074749  -6.892377  4.848379 -1.350330 -1.203844 -1.776470\n",
       "\n",
       "[8000 rows x 6 columns]"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# The outermost index represents the instance number\n",
    "# whereas the inner index represents the index of the particular index\n",
    "# within that instance.\n",
    "X"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "pandas provides a simple way to access a range of value in the multi-indexed dataframe:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "timepoint\n",
       "0     0.351565\n",
       "1     0.351565\n",
       "2    -0.095881\n",
       "3     1.624657\n",
       "4     1.187864\n",
       "        ...   \n",
       "95    0.039951\n",
       "96   -0.029297\n",
       "97    0.000000\n",
       "98    0.000000\n",
       "99   -0.007990\n",
       "Name: gyro_1, Length: 100, dtype: float64"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Select:\n",
    "# * the fourth variable (gyroscope 1)\n",
    "# * of the first instance (trial 1 = 0 in python)\n",
    "# * values at all 100 timestamps\n",
    "#\n",
    "X.loc[0, \"gyro_1\"]"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Or if you want to access the individual values:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "-1.27952"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Select:\n",
    "# * the fifth time time point (5 = 4 in python, because of 0-indexing)\n",
    "# * the third variable (accelerometer 3)\n",
    "# * of the forty-third instance (trial 43 = 42 in python)\n",
    "\n",
    "X.loc[(42, 4), \"accel_3\"]"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.1.2 preferred format 2 - `numpy3D` specification"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`numpy3D` = 3D `np.ndarray` with index (instance, variable, time)\n",
    "\n",
    "instance/time index is interpreted as integer\n",
    "\n",
    "IMPORTANT: unlike `pd-multiindex`, this assumes:\n",
    "\n",
    "* all individual series have the same length\n",
    "* all individual series have the same index"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sktime.datasets import load_italy_power_demand\n",
    "\n",
    "# load an example time series panel in numpy mtype\n",
    "X, _ = load_italy_power_demand(return_type=\"numpy3D\")"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The Italy power demand dataset has:\n",
    "\n",
    "* 1096 individual time series instances = single days of total power demand (mean subtracted)\n",
    "* one single variable per time series instances, unnamed in numpy\n",
    "* individual time series are observed at 24 time (period) points (the same number for all instances)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(1096, 1, 24)"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# (num_instances, num_variables, length)\n",
    "X.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sktime.datasets import load_basic_motions\n",
    "\n",
    "# load an example time series panel in numpy mtype\n",
    "X, _ = load_basic_motions(return_type=\"numpy3D\")"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The basic motions dataset has:\n",
    "\n",
    "* 80 individual time series instances = trials = person engaging in activity (running, badminton, etc)\n",
    "* six variables per time series instance, unnamed in numpy\n",
    "* individual time series are observed at 100 time points (the same number for all instances)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(80, 6, 100)"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X.shape"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2.2 Time Series Classification, Regression, Clustering - Basic Vignettes\n",
    "\n",
    "Above tasks are very similar to \"tabular\" classification, regression, clustering, as in `sklearn`\n",
    "\n",
    "Main distinction:\n",
    "* in \"tabular\" classification etc, one (feature) instance row vector of features\n",
    "* in TSC, one (feature) instance is a full time series, possibly unequal length, distinct index set"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![](./img/tsc.png)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "More formally:\n",
    "\n",
    "* \"tabular\" classification:\n",
    "    * training pairs $(x_1, y_1), \\dots, (x_n, y_n)$\n",
    "        * where $x_i$ are rows of a `pd.DataFrame` (same col types)\n",
    "        * and $y_i \\in \\mathcal{C}$ for a finite set $\\mathcal{C}$\n",
    "    * is used to train a classifier that\n",
    "        * for a new `pd.DataFrame` row $x_*$\n",
    "        * predicts $y_* \\in \\mathcal{C}$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "* time series classification:\n",
    "    * training pairs $(x_1, y_1), \\dots, (x_n, y_n)$\n",
    "        * where $x_i$ are time series instances, from a certain domain\n",
    "        * and $y_i \\in \\mathcal{C}$ for a finite set $\\mathcal{C}$\n",
    "    * is used to train a classifier that\n",
    "        * for a new time series instance $x_*$\n",
    "        * predicts $y_* \\in \\mathcal{C}$"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "very similar for time series regression, clustering - exercise left to reader :-)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`sktime` design implications:\n",
    "\n",
    "* need representation of collections of time series (panels),\n",
    "    see tutorial [In-memory data representations and data loading](AA_datatypes_and_datasets.ipynb) for more details on representation of Panel data.\n",
    "    * same as in \"adjacent\" learning tasks, e.g., panel forecasting\n",
    "    * same as for transformation estimators\n",
    "* algorithms that use sequentiality, can deal with unequal length, missing values etc \n",
    "* algorithms usually based on distances or kernels between time series - need to cover that in framework\n",
    "* but we can use familiar `fit` / `predict` and `scikit-learn` / `scikit-base` interface!"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.2.3 Time Series Classification - deployment vignette"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Basic deployment vignette for TSC:\n",
    "\n",
    "1. load/setup training data, `X` in a `Panel` (more specifically `numpy3D`) format, `y` as 1D `np.ndarray`\n",
    "2. load/setup new data for prediction (can be done after 3 too)\n",
    "3. specify the classifier using `sklearn`-like syntax\n",
    "4. fit classifier to training data, `fit(X, y)`\n",
    "5. predict labels on new data, `predict(X_new)`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "# steps 1, 2 - prepare osuleaf dataset (train and new)\n",
    "from sktime.datasets import load_italy_power_demand\n",
    "\n",
    "X_train, y_train = load_italy_power_demand(split=\"train\", return_type=\"numpy3D\")\n",
    "X_new, _ = load_italy_power_demand(split=\"test\", return_type=\"numpy3D\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(67, 1, 24)"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# this is in numpy3D format, but could also be pd-multiindex or other\n",
    "X_train.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(67,)"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# y is a 1D np.ndarray of labels - same length as number of instances in X_train\n",
    "y_train.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "# step 3 - specify the classifier\n",
    "from sktime.classification.distance_based import KNeighborsTimeSeriesClassifier\n",
    "\n",
    "# example 1 - 3-NN with simple dynamic time warping distance (requires numba)\n",
    "clf = KNeighborsTimeSeriesClassifier(n_neighbors=3)\n",
    "\n",
    "# example 2 - custom distance:\n",
    "# 3-nearest neighbour classifier with Euclidean distance (on flattened time series)\n",
    "# (requires scipy)\n",
    "from sktime.classification.distance_based import KNeighborsTimeSeriesClassifier\n",
    "from sktime.dists_kernels import FlatDist, ScipyDist\n",
    "\n",
    "eucl_dist = FlatDist(ScipyDist())\n",
    "clf = KNeighborsTimeSeriesClassifier(n_neighbors=3, distance=eucl_dist)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "we could specify any `sktime` classifier here - the rest remains the same!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'algorithm': 'brute',\n",
       " 'distance': FlatDist(transformer=ScipyDist()),\n",
       " 'distance_mtype': None,\n",
       " 'distance_params': None,\n",
       " 'leaf_size': 30,\n",
       " 'n_jobs': None,\n",
       " 'n_neighbors': 3,\n",
       " 'pass_train_distances': False,\n",
       " 'weights': 'uniform',\n",
       " 'distance__transformer': ScipyDist(),\n",
       " 'distance__transformer__colalign': 'intersect',\n",
       " 'distance__transformer__metric': 'euclidean',\n",
       " 'distance__transformer__metric_kwargs': None,\n",
       " 'distance__transformer__p': 2,\n",
       " 'distance__transformer__var_weights': None}"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# all classifiers is scikit-learn / scikit-base compatible!\n",
    "# nested parameter interface via get_params, set_params\n",
    "clf.get_params()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<style>#sk-9c2bbf5d-93db-4d45-986c-fcb5e871f8f2 {\n",
       "    /* Definition of color scheme common for light and dark mode */\n",
       "    --sklearn-color-text: black;\n",
       "    --sklearn-color-line: gray;\n",
       "    /* Definition of color scheme for objects */\n",
       "    --sklearn-color-level-0: #fff5e6;\n",
       "    --sklearn-color-level-1: #f6e4d2;\n",
       "    --sklearn-color-level-2: #ffe0b3;\n",
       "    --sklearn-color-level-3: chocolate;\n",
       "\n",
       "    /* Specific color for light theme */\n",
       "    --sklearn-color-text-on-default-background: var(--theme-code-foreground, var(--jp-content-font-color1, black));\n",
       "    --sklearn-color-background: var(--theme-background, var(--jp-layout-color0, white));\n",
       "    --sklearn-color-border-box: var(--theme-code-foreground, var(--jp-content-font-color1, black));\n",
       "    --sklearn-color-icon: #696969;\n",
       "\n",
       "    @media (prefers-color-scheme: dark) {\n",
       "      /* Redefinition of color scheme for dark theme */\n",
       "      --sklearn-color-text-on-default-background: var(--theme-code-foreground, var(--jp-content-font-color1, white));\n",
       "      --sklearn-color-background: var(--theme-background, var(--jp-layout-color0, #111));\n",
       "      --sklearn-color-border-box: var(--theme-code-foreground, var(--jp-content-font-color1, white));\n",
       "      --sklearn-color-icon: #878787;\n",
       "    }\n",
       "  }\n",
       "\n",
       "  #sk-9c2bbf5d-93db-4d45-986c-fcb5e871f8f2 {\n",
       "    color: var(--sklearn-color-text);\n",
       "  }\n",
       "\n",
       "  #sk-9c2bbf5d-93db-4d45-986c-fcb5e871f8f2 pre {\n",
       "    padding: 0;\n",
       "  }\n",
       "\n",
       "  #sk-9c2bbf5d-93db-4d45-986c-fcb5e871f8f2 input.sk-hidden--visually {\n",
       "    border: 0;\n",
       "    clip: rect(1px 1px 1px 1px);\n",
       "    clip: rect(1px, 1px, 1px, 1px);\n",
       "    height: 1px;\n",
       "    margin: -1px;\n",
       "    overflow: hidden;\n",
       "    padding: 0;\n",
       "    position: absolute;\n",
       "    width: 1px;\n",
       "  }\n",
       "\n",
       "  #sk-9c2bbf5d-93db-4d45-986c-fcb5e871f8f2 div.sk-dashed-wrapped {\n",
       "    border: 1px dashed var(--sklearn-color-line);\n",
       "    margin: 0 0.4em 0.5em 0.4em;\n",
       "    box-sizing: border-box;\n",
       "    padding-bottom: 0.4em;\n",
       "    background-color: var(--sklearn-color-background);\n",
       "  }\n",
       "\n",
       "  #sk-9c2bbf5d-93db-4d45-986c-fcb5e871f8f2 div.sk-container {\n",
       "    /* jupyter's `normalize.less` sets `[hidden] { display: none; }`\n",
       "       but bootstrap.min.css set `[hidden] { display: none !important; }`\n",
       "       so we also need the `!important` here to be able to override the\n",
       "       default hidden behavior on the sphinx rendered scikit-learn.org.\n",
       "       See: https://github.com/scikit-learn/scikit-learn/issues/21755 */\n",
       "    display: inline-block !important;\n",
       "    position: relative;\n",
       "  }\n",
       "\n",
       "  #sk-9c2bbf5d-93db-4d45-986c-fcb5e871f8f2 div.sk-text-repr-fallback {\n",
       "    display: none;\n",
       "  }\n",
       "\n",
       "  div.sk-parallel-item,\n",
       "  div.sk-serial,\n",
       "  div.sk-item {\n",
       "    /* draw centered vertical line to link estimators */\n",
       "    background-image: linear-gradient(var(--sklearn-color-text-on-default-background), var(--sklearn-color-text-on-default-background));\n",
       "    background-size: 2px 100%;\n",
       "    background-repeat: no-repeat;\n",
       "    background-position: center center;\n",
       "  }\n",
       "\n",
       "  /* Parallel-specific style estimator block */\n",
       "\n",
       "  #sk-9c2bbf5d-93db-4d45-986c-fcb5e871f8f2 div.sk-parallel-item::after {\n",
       "    content: \"\";\n",
       "    width: 100%;\n",
       "    border-bottom: 2px solid var(--sklearn-color-text-on-default-background);\n",
       "    flex-grow: 1;\n",
       "  }\n",
       "\n",
       "  #sk-9c2bbf5d-93db-4d45-986c-fcb5e871f8f2 div.sk-parallel {\n",
       "    display: flex;\n",
       "    align-items: stretch;\n",
       "    justify-content: center;\n",
       "    background-color: var(--sklearn-color-background);\n",
       "    position: relative;\n",
       "  }\n",
       "\n",
       "  #sk-9c2bbf5d-93db-4d45-986c-fcb5e871f8f2 div.sk-parallel-item {\n",
       "    display: flex;\n",
       "    flex-direction: column;\n",
       "  }\n",
       "\n",
       "  #sk-9c2bbf5d-93db-4d45-986c-fcb5e871f8f2 div.sk-parallel-item:first-child::after {\n",
       "    align-self: flex-end;\n",
       "    width: 50%;\n",
       "  }\n",
       "\n",
       "  #sk-9c2bbf5d-93db-4d45-986c-fcb5e871f8f2 div.sk-parallel-item:last-child::after {\n",
       "    align-self: flex-start;\n",
       "    width: 50%;\n",
       "  }\n",
       "\n",
       "  #sk-9c2bbf5d-93db-4d45-986c-fcb5e871f8f2 div.sk-parallel-item:only-child::after {\n",
       "    width: 0;\n",
       "  }\n",
       "\n",
       "  /* Serial-specific style estimator block */\n",
       "\n",
       "  #sk-9c2bbf5d-93db-4d45-986c-fcb5e871f8f2 div.sk-serial {\n",
       "    display: flex;\n",
       "    flex-direction: column;\n",
       "    align-items: center;\n",
       "    background-color: var(--sklearn-color-background);\n",
       "    padding-right: 1em;\n",
       "    padding-left: 1em;\n",
       "  }\n",
       "\n",
       "\n",
       "  /* Toggleable style: style used for estimator/Pipeline/ColumnTransformer box that is\n",
       "  clickable and can be expanded/collapsed.\n",
       "  - Pipeline and ColumnTransformer use this feature and define the default style\n",
       "  - Estimators will overwrite some part of the style using the `sk-estimator` class\n",
       "  */\n",
       "\n",
       "  /* Pipeline and ColumnTransformer style (default) */\n",
       "\n",
       "  #sk-9c2bbf5d-93db-4d45-986c-fcb5e871f8f2 div.sk-toggleable {\n",
       "    /* Default theme specific background. It is overwritten whether we have a\n",
       "    specific estimator or a Pipeline/ColumnTransformer */\n",
       "    background-color: var(--sklearn-color-background);\n",
       "  }\n",
       "\n",
       "  /* Toggleable label */\n",
       "  #sk-9c2bbf5d-93db-4d45-986c-fcb5e871f8f2 label.sk-toggleable__label {\n",
       "    cursor: pointer;\n",
       "    display: block;\n",
       "    width: 100%;\n",
       "    margin-bottom: 0;\n",
       "    padding: 0.5em;\n",
       "    box-sizing: border-box;\n",
       "    text-align: center;\n",
       "  }\n",
       "\n",
       "  #sk-9c2bbf5d-93db-4d45-986c-fcb5e871f8f2 label.sk-toggleable__label-arrow:before {\n",
       "    /* Arrow on the left of the label */\n",
       "    content: \"▸\";\n",
       "    float: left;\n",
       "    margin-right: 0.25em;\n",
       "    color: var(--sklearn-color-icon);\n",
       "  }\n",
       "\n",
       "  #sk-9c2bbf5d-93db-4d45-986c-fcb5e871f8f2 label.sk-toggleable__label-arrow:hover:before {\n",
       "    color: var(--sklearn-color-text);\n",
       "  }\n",
       "\n",
       "  /* Toggleable content - dropdown */\n",
       "\n",
       "  #sk-9c2bbf5d-93db-4d45-986c-fcb5e871f8f2 div.sk-toggleable__content {\n",
       "    max-height: 0;\n",
       "    max-width: 0;\n",
       "    overflow: hidden;\n",
       "    text-align: left;\n",
       "    background-color: var(--sklearn-color-level-0);\n",
       "  }\n",
       "\n",
       "  #sk-9c2bbf5d-93db-4d45-986c-fcb5e871f8f2 div.sk-toggleable__content pre {\n",
       "    margin: 0.2em;\n",
       "    border-radius: 0.25em;\n",
       "    color: var(--sklearn-color-text);\n",
       "    background-color: var(--sklearn-color-level-0);\n",
       "  }\n",
       "\n",
       "  #sk-9c2bbf5d-93db-4d45-986c-fcb5e871f8f2 input.sk-toggleable__control:checked~div.sk-toggleable__content {\n",
       "    /* Expand drop-down */\n",
       "    max-height: 200px;\n",
       "    max-width: 100%;\n",
       "    overflow: auto;\n",
       "  }\n",
       "\n",
       "  #sk-9c2bbf5d-93db-4d45-986c-fcb5e871f8f2 input.sk-toggleable__control:checked~label.sk-toggleable__label-arrow:before {\n",
       "    content: \"▾\";\n",
       "  }\n",
       "\n",
       "  /* Pipeline/ColumnTransformer-specific style */\n",
       "\n",
       "  #sk-9c2bbf5d-93db-4d45-986c-fcb5e871f8f2 div.sk-label input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
       "    color: var(--sklearn-color-text);\n",
       "    background-color: var(--sklearn-color-level-2);\n",
       "  }\n",
       "\n",
       "  /* Estimator-specific style */\n",
       "\n",
       "  /* Colorize estimator box */\n",
       "  #sk-9c2bbf5d-93db-4d45-986c-fcb5e871f8f2 div.sk-estimator input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
       "    /* unfitted */\n",
       "    background-color: var(--sklearn-color-level-2);\n",
       "  }\n",
       "\n",
       "  #sk-9c2bbf5d-93db-4d45-986c-fcb5e871f8f2 div.sk-label label.sk-toggleable__label,\n",
       "  #sk-9c2bbf5d-93db-4d45-986c-fcb5e871f8f2 div.sk-label label {\n",
       "    /* The background is the default theme color */\n",
       "    color: var(--sklearn-color-text-on-default-background);\n",
       "  }\n",
       "\n",
       "  /* On hover, darken the color of the background */\n",
       "  #sk-9c2bbf5d-93db-4d45-986c-fcb5e871f8f2 div.sk-label:hover label.sk-toggleable__label {\n",
       "    color: var(--sklearn-color-text);\n",
       "    background-color: var(--sklearn-color-level-2);\n",
       "  }\n",
       "\n",
       "  /* Estimator label */\n",
       "\n",
       "  #sk-9c2bbf5d-93db-4d45-986c-fcb5e871f8f2 div.sk-label label {\n",
       "    font-family: monospace;\n",
       "    font-weight: bold;\n",
       "    display: inline-block;\n",
       "    line-height: 1.2em;\n",
       "  }\n",
       "\n",
       "  #sk-9c2bbf5d-93db-4d45-986c-fcb5e871f8f2 div.sk-label-container {\n",
       "    text-align: center;\n",
       "  }\n",
       "\n",
       "  /* Estimator-specific */\n",
       "  #sk-9c2bbf5d-93db-4d45-986c-fcb5e871f8f2 div.sk-estimator {\n",
       "    font-family: monospace;\n",
       "    border: 1px dotted var(--sklearn-color-border-box);\n",
       "    border-radius: 0.25em;\n",
       "    box-sizing: border-box;\n",
       "    margin-bottom: 0.5em;\n",
       "    background-color: var(--sklearn-color-level-0);\n",
       "  }\n",
       "\n",
       "  /* on hover */\n",
       "  #sk-9c2bbf5d-93db-4d45-986c-fcb5e871f8f2 div.sk-estimator:hover {\n",
       "    background-color: var(--sklearn-color-level-2);\n",
       "  }\n",
       "\n",
       "  /* Specification for estimator info */\n",
       "\n",
       "  .sk-estimator-doc-link,\n",
       "  a:link.sk-estimator-doc-link,\n",
       "  a:visited.sk-estimator-doc-link {\n",
       "    float: right;\n",
       "    font-size: smaller;\n",
       "    line-height: 1em;\n",
       "    font-family: monospace;\n",
       "    background-color: var(--sklearn-color-background);\n",
       "    border-radius: 1em;\n",
       "    height: 1em;\n",
       "    width: 1em;\n",
       "    text-decoration: none !important;\n",
       "    margin-left: 1ex;\n",
       "    border: var(--sklearn-color-level-1) 1pt solid;\n",
       "    color: var(--sklearn-color-level-1);\n",
       "  }\n",
       "\n",
       "  /* On hover */\n",
       "  div.sk-estimator:hover .sk-estimator-doc-link:hover,\n",
       "  .sk-estimator-doc-link:hover,\n",
       "  div.sk-label-container:hover .sk-estimator-doc-link:hover,\n",
       "  .sk-estimator-doc-link:hover {\n",
       "    background-color: var(--sklearn-color-level-3);\n",
       "    color: var(--sklearn-color-background);\n",
       "    text-decoration: none;\n",
       "  }\n",
       "\n",
       "  /* Span, style for the box shown on hovering the info icon */\n",
       "  .sk-estimator-doc-link span {\n",
       "    display: none;\n",
       "    z-index: 9999;\n",
       "    position: relative;\n",
       "    font-weight: normal;\n",
       "    right: .2ex;\n",
       "    padding: .5ex;\n",
       "    margin: .5ex;\n",
       "    width: min-content;\n",
       "    min-width: 20ex;\n",
       "    max-width: 50ex;\n",
       "    color: var(--sklearn-color-text);\n",
       "    box-shadow: 2pt 2pt 4pt #999;\n",
       "    background: var(--sklearn-color-level-0);\n",
       "    border: .5pt solid var(--sklearn-color-level-3);\n",
       "  }\n",
       "\n",
       "  .sk-estimator-doc-link:hover span {\n",
       "    display: block;\n",
       "  }\n",
       "\n",
       "  /* \"?\"-specific style due to the `<a>` HTML tag */\n",
       "\n",
       "  #sk-9c2bbf5d-93db-4d45-986c-fcb5e871f8f2 a.estimator_doc_link {\n",
       "    float: right;\n",
       "    font-size: 1rem;\n",
       "    line-height: 1em;\n",
       "    font-family: monospace;\n",
       "    background-color: var(--sklearn-color-background);\n",
       "    border-radius: 1rem;\n",
       "    height: 1rem;\n",
       "    width: 1rem;\n",
       "    text-decoration: none;\n",
       "    color: var(--sklearn-color-level-1);\n",
       "    border: var(--sklearn-color-level-1) 1pt solid;\n",
       "  }\n",
       "\n",
       "  /* On hover */\n",
       "  #sk-9c2bbf5d-93db-4d45-986c-fcb5e871f8f2 a.estimator_doc_link:hover {\n",
       "    background-color: var(--sklearn-color-level-3);\n",
       "    color: var(--sklearn-color-background);\n",
       "    text-decoration: none;\n",
       "  }\n",
       "</style><div id='sk-9c2bbf5d-93db-4d45-986c-fcb5e871f8f2' class=\"sk-top-container\"><div class=\"sk-text-repr-fallback\"><pre>KNeighborsTimeSeriesClassifier(distance=FlatDist(transformer=ScipyDist()),\n",
       "                               n_neighbors=3)</pre><b>Please rerun this cell to show the HTML repr or trust the notebook.</b></div><div class=\"sk-container\" hidden><div class=\"sk-item sk-dashed-wrapped\"><div class='sk-label-container'><div class=\"sk-label sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=UUID('90260876-feb2-4d89-8074-c5da4f8d5ca5') type=\"checkbox\" ><label for=UUID('90260876-feb2-4d89-8074-c5da4f8d5ca5') class='sk-toggleable__label sk-toggleable__label-arrow'>KNeighborsTimeSeriesClassifier<a class=\"sk-estimator-doc-link\" rel=\"noreferrer\" target=\"_blank\" href=\"https://www.sktime.net/en/v0.35.0/api_reference/auto_generated/sktime.classification.distance_based.KNeighborsTimeSeriesClassifier.html\">?<span>Documentation for KNeighborsTimeSeriesClassifier</span></a></label><div class=\"sk-toggleable__content\"><pre>KNeighborsTimeSeriesClassifier(distance=FlatDist(transformer=ScipyDist()),\n",
       "                               n_neighbors=3)</pre></div></div></div><div class=\"sk-parallel\"><div class=\"sk-parallel-item\"><div class=\"sk-item\"><div class='sk-label-container'><div class=\"sk-label sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=UUID('608b8eac-9f05-4540-b873-cc845faf8d6f') type=\"checkbox\" ><label for=UUID('608b8eac-9f05-4540-b873-cc845faf8d6f') class='sk-toggleable__label sk-toggleable__label-arrow'>distance: FlatDist</label><div class=\"sk-toggleable__content\"><pre>FlatDist(transformer=ScipyDist())</pre></div></div></div><div class=\"sk-serial\"><div class=\"sk-item sk-dashed-wrapped\"><div class=\"sk-parallel\"><div class=\"sk-parallel-item\"><div class=\"sk-item\"><div class='sk-label-container'><div class=\"sk-label sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=UUID('9a3e7644-fc82-4759-9869-97dffa7f7225') type=\"checkbox\" ><label for=UUID('9a3e7644-fc82-4759-9869-97dffa7f7225') class='sk-toggleable__label sk-toggleable__label-arrow'>transformer: ScipyDist</label><div class=\"sk-toggleable__content\"><pre>ScipyDist()</pre></div></div></div><div class=\"sk-serial\"><div class='sk-item'><div class=\"sk-estimator sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=UUID('84626b16-8f1f-48b6-ac6f-70ac5310e877') type=\"checkbox\" ><label for=UUID('84626b16-8f1f-48b6-ac6f-70ac5310e877') class='sk-toggleable__label sk-toggleable__label-arrow'>ScipyDist<a class=\"sk-estimator-doc-link\" rel=\"noreferrer\" target=\"_blank\" href=\"https://www.sktime.net/en/v0.35.0/api_reference/auto_generated/sktime.dists_kernels.scipy_dist.ScipyDist.html\">?<span>Documentation for ScipyDist</span></a></label><div class=\"sk-toggleable__content\"><pre>ScipyDist()</pre></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div>"
      ],
      "text/plain": [
       "KNeighborsTimeSeriesClassifier(distance=FlatDist(transformer=ScipyDist()),\n",
       "                               n_neighbors=3)"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# step 4 - fit/train the classifier\n",
    "clf.fit(X_train, y_train)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# the classifier is now fitted\n",
    "clf.is_fitted"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'classes': array(['1', '2'], dtype='<U1'),\n",
       " 'fit_time': 369,\n",
       " 'knn_estimator': KNeighborsClassifier(algorithm='brute', metric='precomputed', n_neighbors=3),\n",
       " 'n_classes': 2,\n",
       " 'knn_estimator__classes': array(['1', '2'], dtype='<U1'),\n",
       " 'knn_estimator__effective_metric': 'precomputed',\n",
       " 'knn_estimator__effective_metric_params': {},\n",
       " 'knn_estimator__n_features_in': 67,\n",
       " 'knn_estimator__n_samples_fit': 67,\n",
       " 'knn_estimator__outputs_2d': False}"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# and we can inspect fitted parameters if we like\n",
    "clf.get_fitted_params()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [],
   "source": [
    "# step 5 - predict labels on new data\n",
    "y_pred = clf.predict(X_new)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array(['2', '2', '2', ..., '2', '2', '2'], dtype='<U1')"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# y_pred is an 1D np.ndarray, similar to sklearn classification output\n",
    "y_pred"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array(['1', '2'], dtype='<U1'), array([510, 519], dtype=int64))"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# predictions and unique counts, for illustration\n",
    "unique, counts = np.unique(y_pred, return_counts=True)\n",
    "unique, counts"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "all together in one cell:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [],
   "source": [
    "# steps 1, 2 - prepare osuleaf dataset (train and new)\n",
    "from sktime.datasets import load_italy_power_demand\n",
    "\n",
    "X_train, y_train = load_italy_power_demand(split=\"train\", return_type=\"numpy3D\")\n",
    "X_new, _ = load_italy_power_demand(split=\"test\", return_type=\"numpy3D\")\n",
    "\n",
    "# step 3 - specify the classifier\n",
    "from sktime.classification.distance_based import KNeighborsTimeSeriesClassifier\n",
    "from sktime.dists_kernels import FlatDist, ScipyDist\n",
    "\n",
    "eucl_dist = FlatDist(ScipyDist())\n",
    "clf = KNeighborsTimeSeriesClassifier(n_neighbors=3, distance=eucl_dist)\n",
    "\n",
    "# step 4 - fit/train the classifier\n",
    "clf.fit(X_train, y_train)\n",
    "\n",
    "# step 5 - predict labels on new data\n",
    "y_pred = clf.predict(X_new)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.2.4 Time Series Classification - simple evaluation vignette"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Evaluation is similar to `sklearn` classifiers - we split a dataset and evaluate performance on the test set.\n",
    "\n",
    "This includes as additional steps:\n",
    "\n",
    "* splitting the initial, historical data, e.g., using `train_test_split`\n",
    "* comparing predictions with a held out data set"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.956268221574344"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sktime.classification.distance_based import KNeighborsTimeSeriesClassifier\n",
    "from sktime.datasets import load_italy_power_demand\n",
    "\n",
    "# data should be split into train/test\n",
    "X_train, y_train = load_italy_power_demand(split=\"train\", return_type=\"numpy3D\")\n",
    "X_test, y_test = load_italy_power_demand(split=\"test\", return_type=\"numpy3D\")\n",
    "\n",
    "# step 3-5 are the same\n",
    "\n",
    "from sktime.dists_kernels import FlatDist, ScipyDist\n",
    "\n",
    "eucl_dist = FlatDist(ScipyDist())\n",
    "clf = KNeighborsTimeSeriesClassifier(n_neighbors=3, distance=eucl_dist)\n",
    "\n",
    "clf.fit(X_train, y_train)\n",
    "y_pred = clf.predict(X_test)\n",
    "\n",
    "# for simplest evaluation, compare ground truth to predictions\n",
    "from sklearn.metrics import accuracy_score\n",
    "\n",
    "accuracy_score(y_test, y_pred)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.2.5 Time Series Classification - handling multivariate data\n",
    "\n",
    "Introducing three common methods to handle multivariate data:\n",
    "\n",
    "**Classifiers with native multivariate capability**, e.g., `TimeSeriesForestClassifier`.\n",
    "\n",
    "Estimators with the `capability: multivariate` tag support multivariate `X` out of the box. Refer [Section 2.3](#23-searching-for-estimators-estimator-tags) for how to search for these.\n",
    "\n",
    "**Distance aggregation via `IndepDist` or `CombinedDistance`.** \n",
    "\n",
    "`IndepDist` aggregates univariate time series distances across multiple variables to an overall multivariate distance.\n",
    "\n",
    "Mathematically, `IndepDist` represents a multivariate distance $d_g(x,y)$ defined as\n",
    "\n",
    "$$d_g​(x,y)=g(d(x_1​,y_1​),d(x_2​,y_2​),…,d(x_D​,y_D​)),$$\n",
    "\n",
    "where $g$ is an chosen aggregation function such as sum, mean, or maximum.\n",
    "\n",
    "**Distance construction via `CombinedDistance`.**\n",
    "\n",
    "`CombinedDistance` gives more flexibility in choosing the function $g$ above, supporting arbitrary arithmetic operations.\n",
    "\n",
    "The class can also be invoked by convenience syntax using arithmetic operations such as `dist1 + dist2`.\n",
    "\n",
    "For further details on customizing time series distances or kernels, refer to [Tutorial](https://www.sktime.net/en/latest/examples/06_distances_kernels_alignment.html)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`TimeSeriesForestClassifier` is a good example of an estimator which handles multivariate data natively."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sktime.classification.interval_based import TimeSeriesForestClassifier\n",
    "from sktime.datasets import load_arrow_head\n",
    "\n",
    "# step 1-- prepare a dataset (multivariate for demonstration)\n",
    "X_train, y_train = load_arrow_head(split=\"train\")\n",
    "X_new, _ = load_arrow_head(split=\"test\")\n",
    "\n",
    "# step 2-- define the TimeSeriesForestClassifier\n",
    "tsf = TimeSeriesForestClassifier()\n",
    "\n",
    "# step 3-- train the classifier on the data\n",
    "tsf.fit(X_train, y_train)\n",
    "\n",
    "# step 4-- predict labels on the new data\n",
    "y_pred = tsf.predict(X_new[:5])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array(['0', '2', '0', '0', '0'], dtype='<U1')"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y_pred"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Example of `IndepDist` with `sum` Aggregation Function on a Multivariate dataset."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sktime.classification.distance_based import KNeighborsTimeSeriesClassifier\n",
    "from sktime.datasets import load_arrow_head\n",
    "from sktime.dists_kernels.compose_tab_to_panel import FlatDist\n",
    "from sktime.dists_kernels.indep import IndepDist\n",
    "from sktime.dists_kernels.scipy_dist import ScipyDist\n",
    "\n",
    "# step 1-- prepare a dataset (multivariate for demonstrating purposes)\n",
    "X_train, y_train = load_arrow_head(split=\"train\", return_X_y=True)\n",
    "X_new, _ = load_arrow_head(split=\"test\", return_X_y=True)\n",
    "\n",
    "# step 2-- define a classification estimator with distance parameter IndepDist\n",
    "indep_dist_sum = IndepDist(dist=FlatDist(ScipyDist()), aggfun=\"sum\")\n",
    "knn_sum = KNeighborsTimeSeriesClassifier(distance=indep_dist_sum)\n",
    "\n",
    "# step 3-- train the models with the data\n",
    "knn_sum.fit(X_train, y_train)\n",
    "\n",
    "# step 4-- predict labels on new data\n",
    "y_pred = knn_sum.predict(X_new[:5])  # Smaller set for faster runtime."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`IndepDist` provides the choice of being able to select `aggfun` parameter out of the many choices - `sum`, `mean`, `median`, `max`, `min`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Prediction with sum aggregation:  ['0' '0' '0' '0' '0']\n"
     ]
    }
   ],
   "source": [
    "print(\"Prediction with sum aggregation: \", y_pred)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Below is another implementation using `CombinedDistance` which applies `DtwDist()` on separate components."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sktime.classification.distance_based import KNeighborsTimeSeriesClassifier\n",
    "from sktime.datasets import load_arrow_head\n",
    "from sktime.dists_kernels.algebra import CombinedDistance\n",
    "from sktime.dists_kernels.compose_tab_to_panel import AggrDist, FlatDist\n",
    "from sktime.dists_kernels.scipy_dist import ScipyDist\n",
    "\n",
    "# step 1-- load a dataset\n",
    "X_train, y_train = load_arrow_head(split=\"train\", return_X_y=True)\n",
    "X_new, _ = load_arrow_head(split=\"test\", return_X_y=True)\n",
    "\n",
    "# step 2-- setup combined distance\n",
    "combined_dist = CombinedDistance([FlatDist(ScipyDist()), AggrDist(ScipyDist())])\n",
    "\n",
    "## step 3-- initialize the classifier\n",
    "knn_combined_dist = KNeighborsTimeSeriesClassifier(distance=combined_dist)\n",
    "\n",
    "## step 4-- train the classifier\n",
    "knn_combined_dist.fit(X_train, y_train)\n",
    "\n",
    "## step 5-- obtain the predictions from the classifier.\n",
    "y_pred = knn_combined_dist.predict(X_new[:5])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array(['0', '0', '0', '0', '0'], dtype='<U1')"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y_pred"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.2.6 Time Series Regression - basic vignettes"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "TSR vignettes are exactly the same as TSC, except that:\n",
    "\n",
    "* `y` in `fit` input and `predict` output should be float 1D `np.ndarray`, not categorical\n",
    "* other algorithms are commonly used and/or performant"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [],
   "source": [
    "# steps 1, 2 - prepare dataset (train and new)\n",
    "from sktime.datasets import load_covid_3month\n",
    "\n",
    "X_train, y_train = load_covid_3month(split=\"train\")\n",
    "y_train = y_train.astype(\"float\")\n",
    "X_new, _ = load_covid_3month(split=\"test\")\n",
    "X_new = X_new.loc[:2]  # smaller dataset for faster notebook runtime\n",
    "\n",
    "# step 3 - specify the regressor\n",
    "from sktime.regression.distance_based import KNeighborsTimeSeriesRegressor\n",
    "\n",
    "clf = KNeighborsTimeSeriesRegressor(n_neighbors=3, distance=eucl_dist)\n",
    "\n",
    "# step 4 - fit/train the regressor\n",
    "clf.fit(X_train, y_train)\n",
    "\n",
    "# step 5 - predict labels on new data\n",
    "y_pred = clf.predict(X_new)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0.02957762, 0.0065062 , 0.00183655])"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y_pred  # predictions are array of float"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.2.7 Time Series Clustering - basic vignettes"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "TS clustering is similar - 1st step is also `fit`, but unsupervised\n",
    "\n",
    "i.e., no labels `y`, and next step is inspecting clusters"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'core_sample_indices': array([ 0,  1,  3,  4,  6,  7,  8,  9, 10, 11, 12, 13, 14, 16, 17, 18, 19,\n",
       "        20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 32, 33, 34, 35, 36, 37,\n",
       "        38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 50, 52, 53, 54, 55, 56, 57,\n",
       "        58, 60, 61, 62, 63, 64, 65], dtype=int64),\n",
       " 'dbscan': DBSCAN(eps=2, metric='precomputed'),\n",
       " 'fit_time': 0,\n",
       " 'labels': array([ 0,  0, -1,  0,  0,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,\n",
       "         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  0,\n",
       "         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  0,\n",
       "         0,  0,  0,  0,  0,  0,  0,  0, -1,  0,  0,  0,  0,  0,  0, -1],\n",
       "       dtype=int64),\n",
       " 'dbscan__components': array([[0.        , 2.21059984, 7.22653506, ..., 2.43397663, 3.42512865,\n",
       "         5.77701453],\n",
       "        [2.21059984, 0.        , 7.31863575, ..., 0.8952782 , 2.01224344,\n",
       "         5.73199202],\n",
       "        [2.98199582, 1.8413087 , 7.5785501 , ..., 1.5676963 , 1.41086552,\n",
       "         5.96418696],\n",
       "        ...,\n",
       "        [3.78429193, 2.68599227, 6.32367754, ..., 2.71202763, 1.36130647,\n",
       "         4.47124464],\n",
       "        [2.43397663, 0.8952782 , 7.59888847, ..., 0.        , 1.98453315,\n",
       "         5.99830821],\n",
       "        [3.42512865, 2.01224344, 7.02761342, ..., 1.98453315, 0.        ,\n",
       "         5.27610504]]),\n",
       " 'dbscan__core_sample_indices': array([ 0,  1,  3,  4,  6,  7,  8,  9, 10, 11, 12, 13, 14, 16, 17, 18, 19,\n",
       "        20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 32, 33, 34, 35, 36, 37,\n",
       "        38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 50, 52, 53, 54, 55, 56, 57,\n",
       "        58, 60, 61, 62, 63, 64, 65], dtype=int64),\n",
       " 'dbscan__labels': array([ 0,  0, -1,  0,  0,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,\n",
       "         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  0,\n",
       "         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  0,\n",
       "         0,  0,  0,  0,  0,  0,  0,  0, -1,  0,  0,  0,  0,  0,  0, -1],\n",
       "       dtype=int64),\n",
       " 'dbscan__n_features_in': 67}"
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# step 1 - prepare dataset (train and new)\n",
    "from sktime.datasets import load_italy_power_demand\n",
    "\n",
    "X, _ = load_italy_power_demand(split=\"train\", return_type=\"numpy3D\")\n",
    "\n",
    "# step 2 - specify the clusterer\n",
    "from sktime.clustering.dbscan import TimeSeriesDBSCAN\n",
    "from sktime.dists_kernels import FlatDist, ScipyDist\n",
    "\n",
    "eucl_dist = FlatDist(ScipyDist())\n",
    "clst = TimeSeriesDBSCAN(distance=eucl_dist, eps=2)\n",
    "\n",
    "# step 3 - fit the clusterer to the data\n",
    "clst.fit(X)\n",
    "\n",
    "# step 4 - inspect the clustering\n",
    "clst.get_fitted_params()"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2.3 Searching for estimators, estimator tags"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Estimators in `sktime` are tagged.\n",
    "\n",
    "Tags starting with \"capability\" indicate things the estimator can or cannot do, e.g.,\n",
    "\n",
    "* `\"capability:missing_values\"` - dealing with missing values\n",
    "* `\"capability:multivariate\"` - dealing with multivariate input\n",
    "* `\"capability:unequal_length\"` - deaing with time series panels where the individual time series have unequal length and/or unequal index"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "all tags for an estimator scitype (e.g., classifier, regressor) can be inspected by `sktime.registry.all_tags`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>name</th>\n",
       "      <th>scitype</th>\n",
       "      <th>type</th>\n",
       "      <th>description</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>X_inner_mtype</td>\n",
       "      <td>estimator</td>\n",
       "      <td>(list, str)</td>\n",
       "      <td>which machine type(s) is the internal _fit/_pr...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>authors</td>\n",
       "      <td>object</td>\n",
       "      <td>(list, str)</td>\n",
       "      <td>list of authors of the object, each author a G...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>capability:contractable</td>\n",
       "      <td>estimator</td>\n",
       "      <td>bool</td>\n",
       "      <td>contract time setting, does the estimator supp...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>capability:feature_importance</td>\n",
       "      <td>estimator</td>\n",
       "      <td>bool</td>\n",
       "      <td>Can the estimator provide feature importance?</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>capability:missing_values</td>\n",
       "      <td>object</td>\n",
       "      <td>bool</td>\n",
       "      <td>can the estimator handle missing data (NA, np....</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>capability:multioutput</td>\n",
       "      <td>[classifier, regressor]</td>\n",
       "      <td>bool</td>\n",
       "      <td>can the estimator handle multi-output time ser...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>capability:multithreading</td>\n",
       "      <td>[classifier, early_classifier]</td>\n",
       "      <td>bool</td>\n",
       "      <td>can the classifier set n_jobs to use multiple ...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>capability:multivariate</td>\n",
       "      <td>[classifier, clusterer, early_classifier, para...</td>\n",
       "      <td>bool</td>\n",
       "      <td>can the estimator be applied to time series wi...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>capability:predict_proba</td>\n",
       "      <td>[classifier, clusterer]</td>\n",
       "      <td>bool</td>\n",
       "      <td>does the estimator implement a non-default pre...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>capability:train_estimate</td>\n",
       "      <td>estimator</td>\n",
       "      <td>bool</td>\n",
       "      <td>can the estimator estimate its performance on ...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>10</th>\n",
       "      <td>capability:unequal_length</td>\n",
       "      <td>[aligner, classifier, clusterer, early_classif...</td>\n",
       "      <td>bool</td>\n",
       "      <td>can the estimator handle unequal length time s...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>11</th>\n",
       "      <td>classifier_type</td>\n",
       "      <td>classifier</td>\n",
       "      <td>(list, [dictionary, distance, feature, hybrid,...</td>\n",
       "      <td>which type the classifier falls under in the t...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>12</th>\n",
       "      <td>distribution_type</td>\n",
       "      <td>estimator</td>\n",
       "      <td>str</td>\n",
       "      <td>distribution type of data as str</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>13</th>\n",
       "      <td>distribution_type</td>\n",
       "      <td>estimator</td>\n",
       "      <td>str</td>\n",
       "      <td>distribution type of data as str</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>14</th>\n",
       "      <td>env_marker</td>\n",
       "      <td>object</td>\n",
       "      <td>str</td>\n",
       "      <td>environment marker (PEP 508) requirement for e...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>15</th>\n",
       "      <td>fit_is_empty</td>\n",
       "      <td>estimator</td>\n",
       "      <td>bool</td>\n",
       "      <td>does the estimator have an empty fit method?</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>16</th>\n",
       "      <td>handles-missing-data</td>\n",
       "      <td>estimator</td>\n",
       "      <td>bool</td>\n",
       "      <td>can the estimator handle missing data (NA, np....</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>17</th>\n",
       "      <td>maintainers</td>\n",
       "      <td>object</td>\n",
       "      <td>(list, str)</td>\n",
       "      <td>current maintainers of the object, each mainta...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>18</th>\n",
       "      <td>object_type</td>\n",
       "      <td>object</td>\n",
       "      <td>str</td>\n",
       "      <td>type of object: estimator, transformer, regres...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>19</th>\n",
       "      <td>python_dependencies</td>\n",
       "      <td>object</td>\n",
       "      <td>(list, str)</td>\n",
       "      <td>python dependencies of estimator as str or lis...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>20</th>\n",
       "      <td>python_dependencies_alias</td>\n",
       "      <td>object</td>\n",
       "      <td>dict</td>\n",
       "      <td>deprecated tag for dependency import aliases</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>21</th>\n",
       "      <td>python_version</td>\n",
       "      <td>object</td>\n",
       "      <td>str</td>\n",
       "      <td>python version specifier (PEP 440) for estimat...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>22</th>\n",
       "      <td>requires_cython</td>\n",
       "      <td>object</td>\n",
       "      <td>bool</td>\n",
       "      <td>whether the object requires a C compiler prese...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>23</th>\n",
       "      <td>reserved_params</td>\n",
       "      <td>estimator</td>\n",
       "      <td>(list, str)</td>\n",
       "      <td>parameters reserved by the base class and pres...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>24</th>\n",
       "      <td>sktime_version</td>\n",
       "      <td>object</td>\n",
       "      <td>str</td>\n",
       "      <td>sktime version from which this estimator class...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>25</th>\n",
       "      <td>visual_block_kind</td>\n",
       "      <td>estimator</td>\n",
       "      <td>(str, [single, serial, parallel])</td>\n",
       "      <td>how to display html representation of a meta-e...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>26</th>\n",
       "      <td>y_inner_mtype</td>\n",
       "      <td>estimator</td>\n",
       "      <td>(list, str)</td>\n",
       "      <td>which machine type(s) is the internal _fit/_pr...</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                             name                                            scitype                                               type                                        description\n",
       "0                   X_inner_mtype                                          estimator                                        (list, str)  which machine type(s) is the internal _fit/_pr...\n",
       "1                         authors                                             object                                        (list, str)  list of authors of the object, each author a G...\n",
       "2         capability:contractable                                          estimator                                               bool  contract time setting, does the estimator supp...\n",
       "3   capability:feature_importance                                          estimator                                               bool      Can the estimator provide feature importance?\n",
       "4       capability:missing_values                                             object                                               bool  can the estimator handle missing data (NA, np....\n",
       "5          capability:multioutput                            [classifier, regressor]                                               bool  can the estimator handle multi-output time ser...\n",
       "6       capability:multithreading                     [classifier, early_classifier]                                               bool  can the classifier set n_jobs to use multiple ...\n",
       "7         capability:multivariate  [classifier, clusterer, early_classifier, para...                                               bool  can the estimator be applied to time series wi...\n",
       "8        capability:predict_proba                            [classifier, clusterer]                                               bool  does the estimator implement a non-default pre...\n",
       "9       capability:train_estimate                                          estimator                                               bool  can the estimator estimate its performance on ...\n",
       "10      capability:unequal_length  [aligner, classifier, clusterer, early_classif...                                               bool  can the estimator handle unequal length time s...\n",
       "11                classifier_type                                         classifier  (list, [dictionary, distance, feature, hybrid,...  which type the classifier falls under in the t...\n",
       "12              distribution_type                                          estimator                                                str                   distribution type of data as str\n",
       "13              distribution_type                                          estimator                                                str                   distribution type of data as str\n",
       "14                     env_marker                                             object                                                str  environment marker (PEP 508) requirement for e...\n",
       "15                   fit_is_empty                                          estimator                                               bool       does the estimator have an empty fit method?\n",
       "16           handles-missing-data                                          estimator                                               bool  can the estimator handle missing data (NA, np....\n",
       "17                    maintainers                                             object                                        (list, str)  current maintainers of the object, each mainta...\n",
       "18                    object_type                                             object                                                str  type of object: estimator, transformer, regres...\n",
       "19            python_dependencies                                             object                                        (list, str)  python dependencies of estimator as str or lis...\n",
       "20      python_dependencies_alias                                             object                                               dict       deprecated tag for dependency import aliases\n",
       "21                 python_version                                             object                                                str  python version specifier (PEP 440) for estimat...\n",
       "22                requires_cython                                             object                                               bool  whether the object requires a C compiler prese...\n",
       "23                reserved_params                                          estimator                                        (list, str)  parameters reserved by the base class and pres...\n",
       "24                 sktime_version                                             object                                                str  sktime version from which this estimator class...\n",
       "25              visual_block_kind                                          estimator                  (str, [single, serial, parallel])  how to display html representation of a meta-e...\n",
       "26                  y_inner_mtype                                          estimator                                        (list, str)  which machine type(s) is the internal _fit/_pr..."
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sktime.registry import all_tags\n",
    "\n",
    "all_tags(\"classifier\", as_dataframe=True)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "valid estimator types are listed in the `all_tags` docstring, or `sktime.registry.BASE_CLASS_REGISTER`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['aligner',\n",
       " 'classifier',\n",
       " 'clusterer',\n",
       " 'detector',\n",
       " 'early_classifier',\n",
       " 'estimator',\n",
       " 'forecaster',\n",
       " 'global_forecaster',\n",
       " 'metric',\n",
       " 'metric_detection',\n",
       " 'metric_forecasting',\n",
       " 'metric_forecasting_proba',\n",
       " 'network',\n",
       " 'object',\n",
       " 'param_est',\n",
       " 'regressor',\n",
       " 'series-annotator',\n",
       " 'splitter',\n",
       " 'transformer',\n",
       " 'transformer-pairwise',\n",
       " 'transformer-pairwise-panel',\n",
       " 'distribution']"
      ]
     },
     "execution_count": 35,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sktime.registry import get_obj_scitype_list\n",
    "\n",
    "# get only fist table column, the list of types\n",
    "get_obj_scitype_list()"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "to find all estimators of a certain type, use `sktime.registry.all_estimators`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Workspace\\sktime\\sktime\\utils\\dependencies\\_dependencies.py:149: UserWarning: This functionality requires package 'torch' to be present in the python environment, but 'torch' was not found. To install the requirement 'torch', please run: pip install torch` \n",
      "  _raise_at_severity(msg, severity, caller=\"_check_soft_dependencies\")\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>name</th>\n",
       "      <th>object</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>Arsenal</td>\n",
       "      <td>&lt;class 'sktime.classification.kernel_based._ar...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>BOSSEnsemble</td>\n",
       "      <td>&lt;class 'sktime.classification.dictionary_based...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>BOSSVSClassifierPyts</td>\n",
       "      <td>&lt;class 'sktime.classification.dictionary_based...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>BaggingClassifier</td>\n",
       "      <td>&lt;class 'sktime.classification.ensemble._baggin...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>CNNClassifier</td>\n",
       "      <td>&lt;class 'sktime.classification.deep_learning.cn...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>58</th>\n",
       "      <td>TimeSeriesForestClassifier</td>\n",
       "      <td>&lt;class 'sktime.classification.interval_based._...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>59</th>\n",
       "      <td>TimeSeriesSVC</td>\n",
       "      <td>&lt;class 'sktime.classification.kernel_based._sv...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>60</th>\n",
       "      <td>TimeSeriesSVCTslearn</td>\n",
       "      <td>&lt;class 'sktime.classification.kernel_based._sv...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>61</th>\n",
       "      <td>WEASEL</td>\n",
       "      <td>&lt;class 'sktime.classification.dictionary_based...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>62</th>\n",
       "      <td>WeightedEnsembleClassifier</td>\n",
       "      <td>&lt;class 'sktime.classification.ensemble._weight...</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>63 rows × 2 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "                          name                                             object\n",
       "0                      Arsenal  <class 'sktime.classification.kernel_based._ar...\n",
       "1                 BOSSEnsemble  <class 'sktime.classification.dictionary_based...\n",
       "2         BOSSVSClassifierPyts  <class 'sktime.classification.dictionary_based...\n",
       "3            BaggingClassifier  <class 'sktime.classification.ensemble._baggin...\n",
       "4                CNNClassifier  <class 'sktime.classification.deep_learning.cn...\n",
       "..                         ...                                                ...\n",
       "58  TimeSeriesForestClassifier  <class 'sktime.classification.interval_based._...\n",
       "59               TimeSeriesSVC  <class 'sktime.classification.kernel_based._sv...\n",
       "60        TimeSeriesSVCTslearn  <class 'sktime.classification.kernel_based._sv...\n",
       "61                      WEASEL  <class 'sktime.classification.dictionary_based...\n",
       "62  WeightedEnsembleClassifier  <class 'sktime.classification.ensemble._weight...\n",
       "\n",
       "[63 rows x 2 columns]"
      ]
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# list all classifiers in sktime\n",
    "from sktime.registry import all_estimators\n",
    "\n",
    "all_estimators(\"classifier\", as_dataframe=True)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "for listing all estimators of a certain type with a certain capability,\n",
    "use the `filter_tags` argument of `all_estimators`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>name</th>\n",
       "      <th>object</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>BOSSVSClassifierPyts</td>\n",
       "      <td>&lt;class 'sktime.classification.dictionary_based...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>BaggingClassifier</td>\n",
       "      <td>&lt;class 'sktime.classification.ensemble._baggin...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>DummyClassifier</td>\n",
       "      <td>&lt;class 'sktime.classification.dummy._dummy.Dum...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>KNeighborsTimeSeriesClassifier</td>\n",
       "      <td>&lt;class 'sktime.classification.distance_based._...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>KNeighborsTimeSeriesClassifierPyts</td>\n",
       "      <td>&lt;class 'sktime.classification.distance_based._...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>MultiplexClassifier</td>\n",
       "      <td>&lt;class 'sktime.classification.compose._multipl...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>ShapeletLearningClassifierPyts</td>\n",
       "      <td>&lt;class 'sktime.classification.shapelet_based._...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>SklearnClassifierPipeline</td>\n",
       "      <td>&lt;class 'sktime.classification.compose._pipelin...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>TSCGridSearchCV</td>\n",
       "      <td>&lt;class 'sktime.classification.model_selection....</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>TimeSeriesSVC</td>\n",
       "      <td>&lt;class 'sktime.classification.kernel_based._sv...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>10</th>\n",
       "      <td>WeightedEnsembleClassifier</td>\n",
       "      <td>&lt;class 'sktime.classification.ensemble._weight...</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                  name                                             object\n",
       "0                 BOSSVSClassifierPyts  <class 'sktime.classification.dictionary_based...\n",
       "1                    BaggingClassifier  <class 'sktime.classification.ensemble._baggin...\n",
       "2                      DummyClassifier  <class 'sktime.classification.dummy._dummy.Dum...\n",
       "3       KNeighborsTimeSeriesClassifier  <class 'sktime.classification.distance_based._...\n",
       "4   KNeighborsTimeSeriesClassifierPyts  <class 'sktime.classification.distance_based._...\n",
       "5                  MultiplexClassifier  <class 'sktime.classification.compose._multipl...\n",
       "6       ShapeletLearningClassifierPyts  <class 'sktime.classification.shapelet_based._...\n",
       "7            SklearnClassifierPipeline  <class 'sktime.classification.compose._pipelin...\n",
       "8                      TSCGridSearchCV  <class 'sktime.classification.model_selection....\n",
       "9                        TimeSeriesSVC  <class 'sktime.classification.kernel_based._sv...\n",
       "10          WeightedEnsembleClassifier  <class 'sktime.classification.ensemble._weight..."
      ]
     },
     "execution_count": 37,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# list all classifiers in sktime\n",
    "# that can classify panels of time series containing missing data\n",
    "from sktime.registry import all_estimators\n",
    "\n",
    "all_estimators(\n",
    "    \"classifier\",\n",
    "    as_dataframe=True,\n",
    "    filter_tags={\"capability:missing_values\": True},\n",
    ")"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "side note:\n",
    "\n",
    "don't worry about how short the list is - when in doubt, it is always possible to pipeline with `Imputer`\n",
    "\n",
    "as in the next section :-)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2.4 Pipelines, Feature Extraction, Tuning, Composition\n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "similar to `sklearn` for \"tabular\" classification, regression, etc,\n",
    "\n",
    "`sktime` has a rich set of tools for:\n",
    "\n",
    "* feature extraction via transformers\n",
    "* pipeline transformers with any estimator\n",
    "* tuning individual estimators or pipelines via grid search and similar\n",
    "* building ensembles out of individual estimators, or other composites\n",
    "\n",
    "`sktime` is also fully interoperable with `sklearn` interface if `numpy` based data mtypes are used\n",
    "\n",
    "(although this loses support for unequal length time series)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.4.1 Primer on `sktime` transformers for feature extraction"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "all `sktime` transformers work natively with panel data:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th>dim_0</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th rowspan=\"5\" valign=\"top\">0</th>\n",
       "      <th>0</th>\n",
       "      <td>0.267711</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>-0.290155</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>-0.564339</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>-0.870044</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>-0.829027</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th rowspan=\"5\" valign=\"top\">1095</th>\n",
       "      <th>19</th>\n",
       "      <td>-0.425904</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>20</th>\n",
       "      <td>-0.781304</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>21</th>\n",
       "      <td>-0.038512</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>22</th>\n",
       "      <td>-0.637956</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>23</th>\n",
       "      <td>-0.932346</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>26304 rows × 1 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "            dim_0\n",
       "0    0   0.267711\n",
       "     1  -0.290155\n",
       "     2  -0.564339\n",
       "     3  -0.870044\n",
       "     4  -0.829027\n",
       "...           ...\n",
       "1095 19 -0.425904\n",
       "     20 -0.781304\n",
       "     21 -0.038512\n",
       "     22 -0.637956\n",
       "     23 -0.932346\n",
       "\n",
       "[26304 rows x 1 columns]"
      ]
     },
     "execution_count": 38,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sktime.datasets import load_italy_power_demand\n",
    "from sktime.transformations.series.detrend import Detrender\n",
    "\n",
    "# load some panel data\n",
    "X, _ = load_italy_power_demand(return_type=\"pd-multiindex\")\n",
    "\n",
    "# specify a linear detrender\n",
    "detrender = Detrender()\n",
    "\n",
    "# detrend X by removing linear trend from each instance\n",
    "X_detrended = detrender.fit_transform(X)\n",
    "X_detrended"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "for panel tasks such as TSC, TSR, clustering, there are two distinctions to be aware of:\n",
    "\n",
    "* series-to-series transformers transform individual series to series, panels to panels. E.g., instance-wise detrender above\n",
    "* series-to-primitive transformers transform individual series to a set of tabular features. E.g., summary feature extractor\n",
    "\n",
    "either type of transform can be instance-wise:\n",
    "\n",
    "* instance-wise transforms use only the i-th series to transform the i-th series. E.g., instance-wise detrender\n",
    "* non-instance-wise transforms train on all series to transform the i-th series. E.g., PCA, overall mean detrender"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>mean</th>\n",
       "      <th>std</th>\n",
       "      <th>min</th>\n",
       "      <th>max</th>\n",
       "      <th>0.1</th>\n",
       "      <th>0.25</th>\n",
       "      <th>0.5</th>\n",
       "      <th>0.75</th>\n",
       "      <th>0.9</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>-1.041667e-09</td>\n",
       "      <td>1.0</td>\n",
       "      <td>-1.593083</td>\n",
       "      <td>1.464375</td>\n",
       "      <td>-1.372442</td>\n",
       "      <td>-0.805078</td>\n",
       "      <td>0.030207</td>\n",
       "      <td>0.936412</td>\n",
       "      <td>1.218518</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>-1.958333e-09</td>\n",
       "      <td>1.0</td>\n",
       "      <td>-1.630917</td>\n",
       "      <td>1.201393</td>\n",
       "      <td>-1.533955</td>\n",
       "      <td>-0.999388</td>\n",
       "      <td>0.384871</td>\n",
       "      <td>0.735720</td>\n",
       "      <td>1.084018</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>-1.775000e-09</td>\n",
       "      <td>1.0</td>\n",
       "      <td>-1.397118</td>\n",
       "      <td>2.349344</td>\n",
       "      <td>-1.003740</td>\n",
       "      <td>-0.741487</td>\n",
       "      <td>-0.132687</td>\n",
       "      <td>0.265374</td>\n",
       "      <td>1.515756</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>-8.541667e-10</td>\n",
       "      <td>1.0</td>\n",
       "      <td>-1.646458</td>\n",
       "      <td>1.344487</td>\n",
       "      <td>-1.476779</td>\n",
       "      <td>-0.898722</td>\n",
       "      <td>0.266022</td>\n",
       "      <td>0.776495</td>\n",
       "      <td>1.039641</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>-3.416667e-09</td>\n",
       "      <td>1.0</td>\n",
       "      <td>-1.620240</td>\n",
       "      <td>1.303502</td>\n",
       "      <td>-1.511644</td>\n",
       "      <td>-0.978061</td>\n",
       "      <td>0.405495</td>\n",
       "      <td>0.692648</td>\n",
       "      <td>1.061249</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1091</th>\n",
       "      <td>-1.041667e-09</td>\n",
       "      <td>1.0</td>\n",
       "      <td>-1.817799</td>\n",
       "      <td>1.630397</td>\n",
       "      <td>-1.323058</td>\n",
       "      <td>-0.643414</td>\n",
       "      <td>0.081208</td>\n",
       "      <td>0.568453</td>\n",
       "      <td>1.390523</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1092</th>\n",
       "      <td>-4.166666e-10</td>\n",
       "      <td>1.0</td>\n",
       "      <td>-1.550077</td>\n",
       "      <td>1.513605</td>\n",
       "      <td>-1.343747</td>\n",
       "      <td>-0.768526</td>\n",
       "      <td>0.075550</td>\n",
       "      <td>0.857101</td>\n",
       "      <td>1.276013</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1093</th>\n",
       "      <td>4.166667e-09</td>\n",
       "      <td>1.0</td>\n",
       "      <td>-1.706992</td>\n",
       "      <td>1.052255</td>\n",
       "      <td>-1.498879</td>\n",
       "      <td>-1.139943</td>\n",
       "      <td>0.467669</td>\n",
       "      <td>0.713195</td>\n",
       "      <td>0.993797</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1094</th>\n",
       "      <td>1.583333e-09</td>\n",
       "      <td>1.0</td>\n",
       "      <td>-1.673857</td>\n",
       "      <td>2.420163</td>\n",
       "      <td>-0.744173</td>\n",
       "      <td>-0.479768</td>\n",
       "      <td>-0.266538</td>\n",
       "      <td>0.159923</td>\n",
       "      <td>1.550184</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1095</th>\n",
       "      <td>3.495833e-09</td>\n",
       "      <td>1.0</td>\n",
       "      <td>-1.680337</td>\n",
       "      <td>1.461716</td>\n",
       "      <td>-1.488154</td>\n",
       "      <td>-0.810934</td>\n",
       "      <td>0.241501</td>\n",
       "      <td>0.645697</td>\n",
       "      <td>1.184117</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>1096 rows × 9 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "              mean  std       min       max       0.1      0.25       0.5      0.75       0.9\n",
       "0    -1.041667e-09  1.0 -1.593083  1.464375 -1.372442 -0.805078  0.030207  0.936412  1.218518\n",
       "1    -1.958333e-09  1.0 -1.630917  1.201393 -1.533955 -0.999388  0.384871  0.735720  1.084018\n",
       "2    -1.775000e-09  1.0 -1.397118  2.349344 -1.003740 -0.741487 -0.132687  0.265374  1.515756\n",
       "3    -8.541667e-10  1.0 -1.646458  1.344487 -1.476779 -0.898722  0.266022  0.776495  1.039641\n",
       "4    -3.416667e-09  1.0 -1.620240  1.303502 -1.511644 -0.978061  0.405495  0.692648  1.061249\n",
       "...            ...  ...       ...       ...       ...       ...       ...       ...       ...\n",
       "1091 -1.041667e-09  1.0 -1.817799  1.630397 -1.323058 -0.643414  0.081208  0.568453  1.390523\n",
       "1092 -4.166666e-10  1.0 -1.550077  1.513605 -1.343747 -0.768526  0.075550  0.857101  1.276013\n",
       "1093  4.166667e-09  1.0 -1.706992  1.052255 -1.498879 -1.139943  0.467669  0.713195  0.993797\n",
       "1094  1.583333e-09  1.0 -1.673857  2.420163 -0.744173 -0.479768 -0.266538  0.159923  1.550184\n",
       "1095  3.495833e-09  1.0 -1.680337  1.461716 -1.488154 -0.810934  0.241501  0.645697  1.184117\n",
       "\n",
       "[1096 rows x 9 columns]"
      ]
     },
     "execution_count": 39,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# example of a series-to-primitive transformer\n",
    "from sktime.transformations.series.summarize import SummaryTransformer\n",
    "\n",
    "# specify summary transformer\n",
    "summary_trafo = SummaryTransformer()\n",
    "\n",
    "# extract summary features - one per instance in the panel\n",
    "X_summaries = summary_trafo.fit_transform(X)\n",
    "X_summaries"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "just like classifiers, we can search for transformers of either type via the right tag:\n",
    "\n",
    "* `\"scitype:transform-input\"` and `\"scitype:transform-output\"` define input and output, e.g., \"series-to-series\" (both are scitype strings)\n",
    "* `\"scitype:instancewise\"` is boolean and tells us whether the transform is instance-wise"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>name</th>\n",
       "      <th>object</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>Catch22</td>\n",
       "      <td>&lt;class 'sktime.transformations.panel.catch22.C...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>Catch22Wrapper</td>\n",
       "      <td>&lt;class 'sktime.transformations.panel.catch22wr...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>FittedParamExtractor</td>\n",
       "      <td>&lt;class 'sktime.transformations.panel.summarize...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>HurstExponentTransformer</td>\n",
       "      <td>&lt;class 'sktime.transformations.series.hurst.Hu...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>RandomIntervalFeatureExtractor</td>\n",
       "      <td>&lt;class 'sktime.transformations.panel.summarize...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>RandomIntervals</td>\n",
       "      <td>&lt;class 'sktime.transformations.panel.random_in...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>RandomShapeletTransform</td>\n",
       "      <td>&lt;class 'sktime.transformations.panel.shapelet_...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>SignatureMoments</td>\n",
       "      <td>&lt;class 'sktime.transformations.series.signatur...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>SignatureTransformer</td>\n",
       "      <td>&lt;class 'sktime.transformations.panel.signature...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>SummaryTransformer</td>\n",
       "      <td>&lt;class 'sktime.transformations.series.summariz...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>10</th>\n",
       "      <td>TSFreshFeatureExtractor</td>\n",
       "      <td>&lt;class 'sktime.transformations.panel.tsfresh.T...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>11</th>\n",
       "      <td>Tabularizer</td>\n",
       "      <td>&lt;class 'sktime.transformations.panel.reduce.Ta...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>12</th>\n",
       "      <td>TimeBinner</td>\n",
       "      <td>&lt;class 'sktime.transformations.panel.reduce.Ti...</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                              name                                             object\n",
       "0                          Catch22  <class 'sktime.transformations.panel.catch22.C...\n",
       "1                   Catch22Wrapper  <class 'sktime.transformations.panel.catch22wr...\n",
       "2             FittedParamExtractor  <class 'sktime.transformations.panel.summarize...\n",
       "3         HurstExponentTransformer  <class 'sktime.transformations.series.hurst.Hu...\n",
       "4   RandomIntervalFeatureExtractor  <class 'sktime.transformations.panel.summarize...\n",
       "5                  RandomIntervals  <class 'sktime.transformations.panel.random_in...\n",
       "6          RandomShapeletTransform  <class 'sktime.transformations.panel.shapelet_...\n",
       "7                 SignatureMoments  <class 'sktime.transformations.series.signatur...\n",
       "8             SignatureTransformer  <class 'sktime.transformations.panel.signature...\n",
       "9               SummaryTransformer  <class 'sktime.transformations.series.summariz...\n",
       "10         TSFreshFeatureExtractor  <class 'sktime.transformations.panel.tsfresh.T...\n",
       "11                     Tabularizer  <class 'sktime.transformations.panel.reduce.Ta...\n",
       "12                      TimeBinner  <class 'sktime.transformations.panel.reduce.Ti..."
      ]
     },
     "execution_count": 40,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# example: looking for all series-to-primitive transformers that are instance-wise\n",
    "from sktime.registry import all_estimators\n",
    "\n",
    "all_estimators(\n",
    "    \"transformer\",\n",
    "    as_dataframe=True,\n",
    "    filter_tags={\n",
    "        \"scitype:transform-input\": \"Series\",\n",
    "        \"scitype:transform-output\": \"Primitives\",\n",
    "        \"scitype:instancewise\": True,\n",
    "    },\n",
    ")"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Further details on transformations and feature extraction can be found in the tutorial 3, transformers.\n",
    "\n",
    "All composition steps therein (e.g., chaining, column subsetting) work together with all estimator types in `sktime`, including classifiers, regressors, clusterers."
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.4.2 Pipelines for time series panel tasks"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "all panel estimators pipeline with `sktime` transformers, via the `*` dunder or `make_pipeline`.\n",
    "\n",
    "The pipeline does the following:\n",
    "\n",
    "* in `fit`: runs the transformers' `fit_transform` in sequence, then `fit` of the panel estimator\n",
    "* in `predict`, runs the fitted transformers' `transform` in sequence, then `predict` of the panel estimator\n",
    "\n",
    "(the logic is same as for `sklearn` pipelines)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<style>#sk-d3643503-8e50-4cd4-be6a-7149db74ebc8 {\n",
       "    /* Definition of color scheme common for light and dark mode */\n",
       "    --sklearn-color-text: black;\n",
       "    --sklearn-color-line: gray;\n",
       "    /* Definition of color scheme for objects */\n",
       "    --sklearn-color-level-0: #fff5e6;\n",
       "    --sklearn-color-level-1: #f6e4d2;\n",
       "    --sklearn-color-level-2: #ffe0b3;\n",
       "    --sklearn-color-level-3: chocolate;\n",
       "\n",
       "    /* Specific color for light theme */\n",
       "    --sklearn-color-text-on-default-background: var(--theme-code-foreground, var(--jp-content-font-color1, black));\n",
       "    --sklearn-color-background: var(--theme-background, var(--jp-layout-color0, white));\n",
       "    --sklearn-color-border-box: var(--theme-code-foreground, var(--jp-content-font-color1, black));\n",
       "    --sklearn-color-icon: #696969;\n",
       "\n",
       "    @media (prefers-color-scheme: dark) {\n",
       "      /* Redefinition of color scheme for dark theme */\n",
       "      --sklearn-color-text-on-default-background: var(--theme-code-foreground, var(--jp-content-font-color1, white));\n",
       "      --sklearn-color-background: var(--theme-background, var(--jp-layout-color0, #111));\n",
       "      --sklearn-color-border-box: var(--theme-code-foreground, var(--jp-content-font-color1, white));\n",
       "      --sklearn-color-icon: #878787;\n",
       "    }\n",
       "  }\n",
       "\n",
       "  #sk-d3643503-8e50-4cd4-be6a-7149db74ebc8 {\n",
       "    color: var(--sklearn-color-text);\n",
       "  }\n",
       "\n",
       "  #sk-d3643503-8e50-4cd4-be6a-7149db74ebc8 pre {\n",
       "    padding: 0;\n",
       "  }\n",
       "\n",
       "  #sk-d3643503-8e50-4cd4-be6a-7149db74ebc8 input.sk-hidden--visually {\n",
       "    border: 0;\n",
       "    clip: rect(1px 1px 1px 1px);\n",
       "    clip: rect(1px, 1px, 1px, 1px);\n",
       "    height: 1px;\n",
       "    margin: -1px;\n",
       "    overflow: hidden;\n",
       "    padding: 0;\n",
       "    position: absolute;\n",
       "    width: 1px;\n",
       "  }\n",
       "\n",
       "  #sk-d3643503-8e50-4cd4-be6a-7149db74ebc8 div.sk-dashed-wrapped {\n",
       "    border: 1px dashed var(--sklearn-color-line);\n",
       "    margin: 0 0.4em 0.5em 0.4em;\n",
       "    box-sizing: border-box;\n",
       "    padding-bottom: 0.4em;\n",
       "    background-color: var(--sklearn-color-background);\n",
       "  }\n",
       "\n",
       "  #sk-d3643503-8e50-4cd4-be6a-7149db74ebc8 div.sk-container {\n",
       "    /* jupyter's `normalize.less` sets `[hidden] { display: none; }`\n",
       "       but bootstrap.min.css set `[hidden] { display: none !important; }`\n",
       "       so we also need the `!important` here to be able to override the\n",
       "       default hidden behavior on the sphinx rendered scikit-learn.org.\n",
       "       See: https://github.com/scikit-learn/scikit-learn/issues/21755 */\n",
       "    display: inline-block !important;\n",
       "    position: relative;\n",
       "  }\n",
       "\n",
       "  #sk-d3643503-8e50-4cd4-be6a-7149db74ebc8 div.sk-text-repr-fallback {\n",
       "    display: none;\n",
       "  }\n",
       "\n",
       "  div.sk-parallel-item,\n",
       "  div.sk-serial,\n",
       "  div.sk-item {\n",
       "    /* draw centered vertical line to link estimators */\n",
       "    background-image: linear-gradient(var(--sklearn-color-text-on-default-background), var(--sklearn-color-text-on-default-background));\n",
       "    background-size: 2px 100%;\n",
       "    background-repeat: no-repeat;\n",
       "    background-position: center center;\n",
       "  }\n",
       "\n",
       "  /* Parallel-specific style estimator block */\n",
       "\n",
       "  #sk-d3643503-8e50-4cd4-be6a-7149db74ebc8 div.sk-parallel-item::after {\n",
       "    content: \"\";\n",
       "    width: 100%;\n",
       "    border-bottom: 2px solid var(--sklearn-color-text-on-default-background);\n",
       "    flex-grow: 1;\n",
       "  }\n",
       "\n",
       "  #sk-d3643503-8e50-4cd4-be6a-7149db74ebc8 div.sk-parallel {\n",
       "    display: flex;\n",
       "    align-items: stretch;\n",
       "    justify-content: center;\n",
       "    background-color: var(--sklearn-color-background);\n",
       "    position: relative;\n",
       "  }\n",
       "\n",
       "  #sk-d3643503-8e50-4cd4-be6a-7149db74ebc8 div.sk-parallel-item {\n",
       "    display: flex;\n",
       "    flex-direction: column;\n",
       "  }\n",
       "\n",
       "  #sk-d3643503-8e50-4cd4-be6a-7149db74ebc8 div.sk-parallel-item:first-child::after {\n",
       "    align-self: flex-end;\n",
       "    width: 50%;\n",
       "  }\n",
       "\n",
       "  #sk-d3643503-8e50-4cd4-be6a-7149db74ebc8 div.sk-parallel-item:last-child::after {\n",
       "    align-self: flex-start;\n",
       "    width: 50%;\n",
       "  }\n",
       "\n",
       "  #sk-d3643503-8e50-4cd4-be6a-7149db74ebc8 div.sk-parallel-item:only-child::after {\n",
       "    width: 0;\n",
       "  }\n",
       "\n",
       "  /* Serial-specific style estimator block */\n",
       "\n",
       "  #sk-d3643503-8e50-4cd4-be6a-7149db74ebc8 div.sk-serial {\n",
       "    display: flex;\n",
       "    flex-direction: column;\n",
       "    align-items: center;\n",
       "    background-color: var(--sklearn-color-background);\n",
       "    padding-right: 1em;\n",
       "    padding-left: 1em;\n",
       "  }\n",
       "\n",
       "\n",
       "  /* Toggleable style: style used for estimator/Pipeline/ColumnTransformer box that is\n",
       "  clickable and can be expanded/collapsed.\n",
       "  - Pipeline and ColumnTransformer use this feature and define the default style\n",
       "  - Estimators will overwrite some part of the style using the `sk-estimator` class\n",
       "  */\n",
       "\n",
       "  /* Pipeline and ColumnTransformer style (default) */\n",
       "\n",
       "  #sk-d3643503-8e50-4cd4-be6a-7149db74ebc8 div.sk-toggleable {\n",
       "    /* Default theme specific background. It is overwritten whether we have a\n",
       "    specific estimator or a Pipeline/ColumnTransformer */\n",
       "    background-color: var(--sklearn-color-background);\n",
       "  }\n",
       "\n",
       "  /* Toggleable label */\n",
       "  #sk-d3643503-8e50-4cd4-be6a-7149db74ebc8 label.sk-toggleable__label {\n",
       "    cursor: pointer;\n",
       "    display: block;\n",
       "    width: 100%;\n",
       "    margin-bottom: 0;\n",
       "    padding: 0.5em;\n",
       "    box-sizing: border-box;\n",
       "    text-align: center;\n",
       "  }\n",
       "\n",
       "  #sk-d3643503-8e50-4cd4-be6a-7149db74ebc8 label.sk-toggleable__label-arrow:before {\n",
       "    /* Arrow on the left of the label */\n",
       "    content: \"▸\";\n",
       "    float: left;\n",
       "    margin-right: 0.25em;\n",
       "    color: var(--sklearn-color-icon);\n",
       "  }\n",
       "\n",
       "  #sk-d3643503-8e50-4cd4-be6a-7149db74ebc8 label.sk-toggleable__label-arrow:hover:before {\n",
       "    color: var(--sklearn-color-text);\n",
       "  }\n",
       "\n",
       "  /* Toggleable content - dropdown */\n",
       "\n",
       "  #sk-d3643503-8e50-4cd4-be6a-7149db74ebc8 div.sk-toggleable__content {\n",
       "    max-height: 0;\n",
       "    max-width: 0;\n",
       "    overflow: hidden;\n",
       "    text-align: left;\n",
       "    background-color: var(--sklearn-color-level-0);\n",
       "  }\n",
       "\n",
       "  #sk-d3643503-8e50-4cd4-be6a-7149db74ebc8 div.sk-toggleable__content pre {\n",
       "    margin: 0.2em;\n",
       "    border-radius: 0.25em;\n",
       "    color: var(--sklearn-color-text);\n",
       "    background-color: var(--sklearn-color-level-0);\n",
       "  }\n",
       "\n",
       "  #sk-d3643503-8e50-4cd4-be6a-7149db74ebc8 input.sk-toggleable__control:checked~div.sk-toggleable__content {\n",
       "    /* Expand drop-down */\n",
       "    max-height: 200px;\n",
       "    max-width: 100%;\n",
       "    overflow: auto;\n",
       "  }\n",
       "\n",
       "  #sk-d3643503-8e50-4cd4-be6a-7149db74ebc8 input.sk-toggleable__control:checked~label.sk-toggleable__label-arrow:before {\n",
       "    content: \"▾\";\n",
       "  }\n",
       "\n",
       "  /* Pipeline/ColumnTransformer-specific style */\n",
       "\n",
       "  #sk-d3643503-8e50-4cd4-be6a-7149db74ebc8 div.sk-label input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
       "    color: var(--sklearn-color-text);\n",
       "    background-color: var(--sklearn-color-level-2);\n",
       "  }\n",
       "\n",
       "  /* Estimator-specific style */\n",
       "\n",
       "  /* Colorize estimator box */\n",
       "  #sk-d3643503-8e50-4cd4-be6a-7149db74ebc8 div.sk-estimator input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
       "    /* unfitted */\n",
       "    background-color: var(--sklearn-color-level-2);\n",
       "  }\n",
       "\n",
       "  #sk-d3643503-8e50-4cd4-be6a-7149db74ebc8 div.sk-label label.sk-toggleable__label,\n",
       "  #sk-d3643503-8e50-4cd4-be6a-7149db74ebc8 div.sk-label label {\n",
       "    /* The background is the default theme color */\n",
       "    color: var(--sklearn-color-text-on-default-background);\n",
       "  }\n",
       "\n",
       "  /* On hover, darken the color of the background */\n",
       "  #sk-d3643503-8e50-4cd4-be6a-7149db74ebc8 div.sk-label:hover label.sk-toggleable__label {\n",
       "    color: var(--sklearn-color-text);\n",
       "    background-color: var(--sklearn-color-level-2);\n",
       "  }\n",
       "\n",
       "  /* Estimator label */\n",
       "\n",
       "  #sk-d3643503-8e50-4cd4-be6a-7149db74ebc8 div.sk-label label {\n",
       "    font-family: monospace;\n",
       "    font-weight: bold;\n",
       "    display: inline-block;\n",
       "    line-height: 1.2em;\n",
       "  }\n",
       "\n",
       "  #sk-d3643503-8e50-4cd4-be6a-7149db74ebc8 div.sk-label-container {\n",
       "    text-align: center;\n",
       "  }\n",
       "\n",
       "  /* Estimator-specific */\n",
       "  #sk-d3643503-8e50-4cd4-be6a-7149db74ebc8 div.sk-estimator {\n",
       "    font-family: monospace;\n",
       "    border: 1px dotted var(--sklearn-color-border-box);\n",
       "    border-radius: 0.25em;\n",
       "    box-sizing: border-box;\n",
       "    margin-bottom: 0.5em;\n",
       "    background-color: var(--sklearn-color-level-0);\n",
       "  }\n",
       "\n",
       "  /* on hover */\n",
       "  #sk-d3643503-8e50-4cd4-be6a-7149db74ebc8 div.sk-estimator:hover {\n",
       "    background-color: var(--sklearn-color-level-2);\n",
       "  }\n",
       "\n",
       "  /* Specification for estimator info */\n",
       "\n",
       "  .sk-estimator-doc-link,\n",
       "  a:link.sk-estimator-doc-link,\n",
       "  a:visited.sk-estimator-doc-link {\n",
       "    float: right;\n",
       "    font-size: smaller;\n",
       "    line-height: 1em;\n",
       "    font-family: monospace;\n",
       "    background-color: var(--sklearn-color-background);\n",
       "    border-radius: 1em;\n",
       "    height: 1em;\n",
       "    width: 1em;\n",
       "    text-decoration: none !important;\n",
       "    margin-left: 1ex;\n",
       "    border: var(--sklearn-color-level-1) 1pt solid;\n",
       "    color: var(--sklearn-color-level-1);\n",
       "  }\n",
       "\n",
       "  /* On hover */\n",
       "  div.sk-estimator:hover .sk-estimator-doc-link:hover,\n",
       "  .sk-estimator-doc-link:hover,\n",
       "  div.sk-label-container:hover .sk-estimator-doc-link:hover,\n",
       "  .sk-estimator-doc-link:hover {\n",
       "    background-color: var(--sklearn-color-level-3);\n",
       "    color: var(--sklearn-color-background);\n",
       "    text-decoration: none;\n",
       "  }\n",
       "\n",
       "  /* Span, style for the box shown on hovering the info icon */\n",
       "  .sk-estimator-doc-link span {\n",
       "    display: none;\n",
       "    z-index: 9999;\n",
       "    position: relative;\n",
       "    font-weight: normal;\n",
       "    right: .2ex;\n",
       "    padding: .5ex;\n",
       "    margin: .5ex;\n",
       "    width: min-content;\n",
       "    min-width: 20ex;\n",
       "    max-width: 50ex;\n",
       "    color: var(--sklearn-color-text);\n",
       "    box-shadow: 2pt 2pt 4pt #999;\n",
       "    background: var(--sklearn-color-level-0);\n",
       "    border: .5pt solid var(--sklearn-color-level-3);\n",
       "  }\n",
       "\n",
       "  .sk-estimator-doc-link:hover span {\n",
       "    display: block;\n",
       "  }\n",
       "\n",
       "  /* \"?\"-specific style due to the `<a>` HTML tag */\n",
       "\n",
       "  #sk-d3643503-8e50-4cd4-be6a-7149db74ebc8 a.estimator_doc_link {\n",
       "    float: right;\n",
       "    font-size: 1rem;\n",
       "    line-height: 1em;\n",
       "    font-family: monospace;\n",
       "    background-color: var(--sklearn-color-background);\n",
       "    border-radius: 1rem;\n",
       "    height: 1rem;\n",
       "    width: 1rem;\n",
       "    text-decoration: none;\n",
       "    color: var(--sklearn-color-level-1);\n",
       "    border: var(--sklearn-color-level-1) 1pt solid;\n",
       "  }\n",
       "\n",
       "  /* On hover */\n",
       "  #sk-d3643503-8e50-4cd4-be6a-7149db74ebc8 a.estimator_doc_link:hover {\n",
       "    background-color: var(--sklearn-color-level-3);\n",
       "    color: var(--sklearn-color-background);\n",
       "    text-decoration: none;\n",
       "  }\n",
       "</style><div id='sk-d3643503-8e50-4cd4-be6a-7149db74ebc8' class=\"sk-top-container\"><div class=\"sk-text-repr-fallback\"><pre>ClassifierPipeline(classifier=KNeighborsTimeSeriesClassifier(),\n",
       "                   transformers=[ExponentTransformer()])</pre><b>Please rerun this cell to show the HTML repr or trust the notebook.</b></div><div class=\"sk-container\" hidden><div class=\"sk-item sk-dashed-wrapped\"><div class='sk-label-container'><div class=\"sk-label sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=UUID('64b54dcb-5b5b-476e-8673-b70d47d12853') type=\"checkbox\" ><label for=UUID('64b54dcb-5b5b-476e-8673-b70d47d12853') class='sk-toggleable__label sk-toggleable__label-arrow'>ClassifierPipeline<a class=\"sk-estimator-doc-link\" rel=\"noreferrer\" target=\"_blank\" href=\"https://www.sktime.net/en/v0.35.0/api_reference/auto_generated/sktime.classification.compose.ClassifierPipeline.html\">?<span>Documentation for ClassifierPipeline</span></a></label><div class=\"sk-toggleable__content\"><pre>ClassifierPipeline(classifier=KNeighborsTimeSeriesClassifier(),\n",
       "                   transformers=[ExponentTransformer()])</pre></div></div></div><div class=\"sk-serial\"><div class='sk-item'><div class=\"sk-estimator sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=UUID('c4750501-1572-43fe-854f-a68422eb7789') type=\"checkbox\" ><label for=UUID('c4750501-1572-43fe-854f-a68422eb7789') class='sk-toggleable__label sk-toggleable__label-arrow'>ExponentTransformer<a class=\"sk-estimator-doc-link\" rel=\"noreferrer\" target=\"_blank\" href=\"https://www.sktime.net/en/v0.35.0/api_reference/auto_generated/sktime.transformations.series.exponent.ExponentTransformer.html\">?<span>Documentation for ExponentTransformer</span></a></label><div class=\"sk-toggleable__content\"><pre>ExponentTransformer()</pre></div></div></div><div class='sk-item'><div class=\"sk-estimator sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=UUID('99122a44-dbe0-4003-bbf7-8ca034d59f42') type=\"checkbox\" ><label for=UUID('99122a44-dbe0-4003-bbf7-8ca034d59f42') class='sk-toggleable__label sk-toggleable__label-arrow'>KNeighborsTimeSeriesClassifier<a class=\"sk-estimator-doc-link\" rel=\"noreferrer\" target=\"_blank\" href=\"https://www.sktime.net/en/v0.35.0/api_reference/auto_generated/sktime.classification.distance_based.KNeighborsTimeSeriesClassifier.html\">?<span>Documentation for KNeighborsTimeSeriesClassifier</span></a></label><div class=\"sk-toggleable__content\"><pre>KNeighborsTimeSeriesClassifier()</pre></div></div></div></div></div></div></div>"
      ],
      "text/plain": [
       "ClassifierPipeline(classifier=KNeighborsTimeSeriesClassifier(),\n",
       "                   transformers=[ExponentTransformer()])"
      ]
     },
     "execution_count": 41,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sktime.classification.distance_based import KNeighborsTimeSeriesClassifier\n",
    "from sktime.transformations.series.exponent import ExponentTransformer\n",
    "\n",
    "pipe = ExponentTransformer() * KNeighborsTimeSeriesClassifier()\n",
    "\n",
    "# this constructs a ClassifierPipeline, which is also a classifier\n",
    "pipe"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {},
   "outputs": [],
   "source": [
    "# alternative to construct:\n",
    "from sktime.pipeline import make_pipeline\n",
    "\n",
    "pipe = make_pipeline(ExponentTransformer(), KNeighborsTimeSeriesClassifier())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<style>#sk-18b979fe-da13-44cf-8bb1-99da8e969c0a {\n",
       "    /* Definition of color scheme common for light and dark mode */\n",
       "    --sklearn-color-text: black;\n",
       "    --sklearn-color-line: gray;\n",
       "    /* Definition of color scheme for objects */\n",
       "    --sklearn-color-level-0: #fff5e6;\n",
       "    --sklearn-color-level-1: #f6e4d2;\n",
       "    --sklearn-color-level-2: #ffe0b3;\n",
       "    --sklearn-color-level-3: chocolate;\n",
       "\n",
       "    /* Specific color for light theme */\n",
       "    --sklearn-color-text-on-default-background: var(--theme-code-foreground, var(--jp-content-font-color1, black));\n",
       "    --sklearn-color-background: var(--theme-background, var(--jp-layout-color0, white));\n",
       "    --sklearn-color-border-box: var(--theme-code-foreground, var(--jp-content-font-color1, black));\n",
       "    --sklearn-color-icon: #696969;\n",
       "\n",
       "    @media (prefers-color-scheme: dark) {\n",
       "      /* Redefinition of color scheme for dark theme */\n",
       "      --sklearn-color-text-on-default-background: var(--theme-code-foreground, var(--jp-content-font-color1, white));\n",
       "      --sklearn-color-background: var(--theme-background, var(--jp-layout-color0, #111));\n",
       "      --sklearn-color-border-box: var(--theme-code-foreground, var(--jp-content-font-color1, white));\n",
       "      --sklearn-color-icon: #878787;\n",
       "    }\n",
       "  }\n",
       "\n",
       "  #sk-18b979fe-da13-44cf-8bb1-99da8e969c0a {\n",
       "    color: var(--sklearn-color-text);\n",
       "  }\n",
       "\n",
       "  #sk-18b979fe-da13-44cf-8bb1-99da8e969c0a pre {\n",
       "    padding: 0;\n",
       "  }\n",
       "\n",
       "  #sk-18b979fe-da13-44cf-8bb1-99da8e969c0a input.sk-hidden--visually {\n",
       "    border: 0;\n",
       "    clip: rect(1px 1px 1px 1px);\n",
       "    clip: rect(1px, 1px, 1px, 1px);\n",
       "    height: 1px;\n",
       "    margin: -1px;\n",
       "    overflow: hidden;\n",
       "    padding: 0;\n",
       "    position: absolute;\n",
       "    width: 1px;\n",
       "  }\n",
       "\n",
       "  #sk-18b979fe-da13-44cf-8bb1-99da8e969c0a div.sk-dashed-wrapped {\n",
       "    border: 1px dashed var(--sklearn-color-line);\n",
       "    margin: 0 0.4em 0.5em 0.4em;\n",
       "    box-sizing: border-box;\n",
       "    padding-bottom: 0.4em;\n",
       "    background-color: var(--sklearn-color-background);\n",
       "  }\n",
       "\n",
       "  #sk-18b979fe-da13-44cf-8bb1-99da8e969c0a div.sk-container {\n",
       "    /* jupyter's `normalize.less` sets `[hidden] { display: none; }`\n",
       "       but bootstrap.min.css set `[hidden] { display: none !important; }`\n",
       "       so we also need the `!important` here to be able to override the\n",
       "       default hidden behavior on the sphinx rendered scikit-learn.org.\n",
       "       See: https://github.com/scikit-learn/scikit-learn/issues/21755 */\n",
       "    display: inline-block !important;\n",
       "    position: relative;\n",
       "  }\n",
       "\n",
       "  #sk-18b979fe-da13-44cf-8bb1-99da8e969c0a div.sk-text-repr-fallback {\n",
       "    display: none;\n",
       "  }\n",
       "\n",
       "  div.sk-parallel-item,\n",
       "  div.sk-serial,\n",
       "  div.sk-item {\n",
       "    /* draw centered vertical line to link estimators */\n",
       "    background-image: linear-gradient(var(--sklearn-color-text-on-default-background), var(--sklearn-color-text-on-default-background));\n",
       "    background-size: 2px 100%;\n",
       "    background-repeat: no-repeat;\n",
       "    background-position: center center;\n",
       "  }\n",
       "\n",
       "  /* Parallel-specific style estimator block */\n",
       "\n",
       "  #sk-18b979fe-da13-44cf-8bb1-99da8e969c0a div.sk-parallel-item::after {\n",
       "    content: \"\";\n",
       "    width: 100%;\n",
       "    border-bottom: 2px solid var(--sklearn-color-text-on-default-background);\n",
       "    flex-grow: 1;\n",
       "  }\n",
       "\n",
       "  #sk-18b979fe-da13-44cf-8bb1-99da8e969c0a div.sk-parallel {\n",
       "    display: flex;\n",
       "    align-items: stretch;\n",
       "    justify-content: center;\n",
       "    background-color: var(--sklearn-color-background);\n",
       "    position: relative;\n",
       "  }\n",
       "\n",
       "  #sk-18b979fe-da13-44cf-8bb1-99da8e969c0a div.sk-parallel-item {\n",
       "    display: flex;\n",
       "    flex-direction: column;\n",
       "  }\n",
       "\n",
       "  #sk-18b979fe-da13-44cf-8bb1-99da8e969c0a div.sk-parallel-item:first-child::after {\n",
       "    align-self: flex-end;\n",
       "    width: 50%;\n",
       "  }\n",
       "\n",
       "  #sk-18b979fe-da13-44cf-8bb1-99da8e969c0a div.sk-parallel-item:last-child::after {\n",
       "    align-self: flex-start;\n",
       "    width: 50%;\n",
       "  }\n",
       "\n",
       "  #sk-18b979fe-da13-44cf-8bb1-99da8e969c0a div.sk-parallel-item:only-child::after {\n",
       "    width: 0;\n",
       "  }\n",
       "\n",
       "  /* Serial-specific style estimator block */\n",
       "\n",
       "  #sk-18b979fe-da13-44cf-8bb1-99da8e969c0a div.sk-serial {\n",
       "    display: flex;\n",
       "    flex-direction: column;\n",
       "    align-items: center;\n",
       "    background-color: var(--sklearn-color-background);\n",
       "    padding-right: 1em;\n",
       "    padding-left: 1em;\n",
       "  }\n",
       "\n",
       "\n",
       "  /* Toggleable style: style used for estimator/Pipeline/ColumnTransformer box that is\n",
       "  clickable and can be expanded/collapsed.\n",
       "  - Pipeline and ColumnTransformer use this feature and define the default style\n",
       "  - Estimators will overwrite some part of the style using the `sk-estimator` class\n",
       "  */\n",
       "\n",
       "  /* Pipeline and ColumnTransformer style (default) */\n",
       "\n",
       "  #sk-18b979fe-da13-44cf-8bb1-99da8e969c0a div.sk-toggleable {\n",
       "    /* Default theme specific background. It is overwritten whether we have a\n",
       "    specific estimator or a Pipeline/ColumnTransformer */\n",
       "    background-color: var(--sklearn-color-background);\n",
       "  }\n",
       "\n",
       "  /* Toggleable label */\n",
       "  #sk-18b979fe-da13-44cf-8bb1-99da8e969c0a label.sk-toggleable__label {\n",
       "    cursor: pointer;\n",
       "    display: block;\n",
       "    width: 100%;\n",
       "    margin-bottom: 0;\n",
       "    padding: 0.5em;\n",
       "    box-sizing: border-box;\n",
       "    text-align: center;\n",
       "  }\n",
       "\n",
       "  #sk-18b979fe-da13-44cf-8bb1-99da8e969c0a label.sk-toggleable__label-arrow:before {\n",
       "    /* Arrow on the left of the label */\n",
       "    content: \"▸\";\n",
       "    float: left;\n",
       "    margin-right: 0.25em;\n",
       "    color: var(--sklearn-color-icon);\n",
       "  }\n",
       "\n",
       "  #sk-18b979fe-da13-44cf-8bb1-99da8e969c0a label.sk-toggleable__label-arrow:hover:before {\n",
       "    color: var(--sklearn-color-text);\n",
       "  }\n",
       "\n",
       "  /* Toggleable content - dropdown */\n",
       "\n",
       "  #sk-18b979fe-da13-44cf-8bb1-99da8e969c0a div.sk-toggleable__content {\n",
       "    max-height: 0;\n",
       "    max-width: 0;\n",
       "    overflow: hidden;\n",
       "    text-align: left;\n",
       "    background-color: var(--sklearn-color-level-0);\n",
       "  }\n",
       "\n",
       "  #sk-18b979fe-da13-44cf-8bb1-99da8e969c0a div.sk-toggleable__content pre {\n",
       "    margin: 0.2em;\n",
       "    border-radius: 0.25em;\n",
       "    color: var(--sklearn-color-text);\n",
       "    background-color: var(--sklearn-color-level-0);\n",
       "  }\n",
       "\n",
       "  #sk-18b979fe-da13-44cf-8bb1-99da8e969c0a input.sk-toggleable__control:checked~div.sk-toggleable__content {\n",
       "    /* Expand drop-down */\n",
       "    max-height: 200px;\n",
       "    max-width: 100%;\n",
       "    overflow: auto;\n",
       "  }\n",
       "\n",
       "  #sk-18b979fe-da13-44cf-8bb1-99da8e969c0a input.sk-toggleable__control:checked~label.sk-toggleable__label-arrow:before {\n",
       "    content: \"▾\";\n",
       "  }\n",
       "\n",
       "  /* Pipeline/ColumnTransformer-specific style */\n",
       "\n",
       "  #sk-18b979fe-da13-44cf-8bb1-99da8e969c0a div.sk-label input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
       "    color: var(--sklearn-color-text);\n",
       "    background-color: var(--sklearn-color-level-2);\n",
       "  }\n",
       "\n",
       "  /* Estimator-specific style */\n",
       "\n",
       "  /* Colorize estimator box */\n",
       "  #sk-18b979fe-da13-44cf-8bb1-99da8e969c0a div.sk-estimator input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
       "    /* unfitted */\n",
       "    background-color: var(--sklearn-color-level-2);\n",
       "  }\n",
       "\n",
       "  #sk-18b979fe-da13-44cf-8bb1-99da8e969c0a div.sk-label label.sk-toggleable__label,\n",
       "  #sk-18b979fe-da13-44cf-8bb1-99da8e969c0a div.sk-label label {\n",
       "    /* The background is the default theme color */\n",
       "    color: var(--sklearn-color-text-on-default-background);\n",
       "  }\n",
       "\n",
       "  /* On hover, darken the color of the background */\n",
       "  #sk-18b979fe-da13-44cf-8bb1-99da8e969c0a div.sk-label:hover label.sk-toggleable__label {\n",
       "    color: var(--sklearn-color-text);\n",
       "    background-color: var(--sklearn-color-level-2);\n",
       "  }\n",
       "\n",
       "  /* Estimator label */\n",
       "\n",
       "  #sk-18b979fe-da13-44cf-8bb1-99da8e969c0a div.sk-label label {\n",
       "    font-family: monospace;\n",
       "    font-weight: bold;\n",
       "    display: inline-block;\n",
       "    line-height: 1.2em;\n",
       "  }\n",
       "\n",
       "  #sk-18b979fe-da13-44cf-8bb1-99da8e969c0a div.sk-label-container {\n",
       "    text-align: center;\n",
       "  }\n",
       "\n",
       "  /* Estimator-specific */\n",
       "  #sk-18b979fe-da13-44cf-8bb1-99da8e969c0a div.sk-estimator {\n",
       "    font-family: monospace;\n",
       "    border: 1px dotted var(--sklearn-color-border-box);\n",
       "    border-radius: 0.25em;\n",
       "    box-sizing: border-box;\n",
       "    margin-bottom: 0.5em;\n",
       "    background-color: var(--sklearn-color-level-0);\n",
       "  }\n",
       "\n",
       "  /* on hover */\n",
       "  #sk-18b979fe-da13-44cf-8bb1-99da8e969c0a div.sk-estimator:hover {\n",
       "    background-color: var(--sklearn-color-level-2);\n",
       "  }\n",
       "\n",
       "  /* Specification for estimator info */\n",
       "\n",
       "  .sk-estimator-doc-link,\n",
       "  a:link.sk-estimator-doc-link,\n",
       "  a:visited.sk-estimator-doc-link {\n",
       "    float: right;\n",
       "    font-size: smaller;\n",
       "    line-height: 1em;\n",
       "    font-family: monospace;\n",
       "    background-color: var(--sklearn-color-background);\n",
       "    border-radius: 1em;\n",
       "    height: 1em;\n",
       "    width: 1em;\n",
       "    text-decoration: none !important;\n",
       "    margin-left: 1ex;\n",
       "    border: var(--sklearn-color-level-1) 1pt solid;\n",
       "    color: var(--sklearn-color-level-1);\n",
       "  }\n",
       "\n",
       "  /* On hover */\n",
       "  div.sk-estimator:hover .sk-estimator-doc-link:hover,\n",
       "  .sk-estimator-doc-link:hover,\n",
       "  div.sk-label-container:hover .sk-estimator-doc-link:hover,\n",
       "  .sk-estimator-doc-link:hover {\n",
       "    background-color: var(--sklearn-color-level-3);\n",
       "    color: var(--sklearn-color-background);\n",
       "    text-decoration: none;\n",
       "  }\n",
       "\n",
       "  /* Span, style for the box shown on hovering the info icon */\n",
       "  .sk-estimator-doc-link span {\n",
       "    display: none;\n",
       "    z-index: 9999;\n",
       "    position: relative;\n",
       "    font-weight: normal;\n",
       "    right: .2ex;\n",
       "    padding: .5ex;\n",
       "    margin: .5ex;\n",
       "    width: min-content;\n",
       "    min-width: 20ex;\n",
       "    max-width: 50ex;\n",
       "    color: var(--sklearn-color-text);\n",
       "    box-shadow: 2pt 2pt 4pt #999;\n",
       "    background: var(--sklearn-color-level-0);\n",
       "    border: .5pt solid var(--sklearn-color-level-3);\n",
       "  }\n",
       "\n",
       "  .sk-estimator-doc-link:hover span {\n",
       "    display: block;\n",
       "  }\n",
       "\n",
       "  /* \"?\"-specific style due to the `<a>` HTML tag */\n",
       "\n",
       "  #sk-18b979fe-da13-44cf-8bb1-99da8e969c0a a.estimator_doc_link {\n",
       "    float: right;\n",
       "    font-size: 1rem;\n",
       "    line-height: 1em;\n",
       "    font-family: monospace;\n",
       "    background-color: var(--sklearn-color-background);\n",
       "    border-radius: 1rem;\n",
       "    height: 1rem;\n",
       "    width: 1rem;\n",
       "    text-decoration: none;\n",
       "    color: var(--sklearn-color-level-1);\n",
       "    border: var(--sklearn-color-level-1) 1pt solid;\n",
       "  }\n",
       "\n",
       "  /* On hover */\n",
       "  #sk-18b979fe-da13-44cf-8bb1-99da8e969c0a a.estimator_doc_link:hover {\n",
       "    background-color: var(--sklearn-color-level-3);\n",
       "    color: var(--sklearn-color-background);\n",
       "    text-decoration: none;\n",
       "  }\n",
       "</style><div id='sk-18b979fe-da13-44cf-8bb1-99da8e969c0a' class=\"sk-top-container\"><div class=\"sk-text-repr-fallback\"><pre>ClassifierPipeline(classifier=KNeighborsTimeSeriesClassifier(),\n",
       "                   transformers=[ExponentTransformer()])</pre><b>Please rerun this cell to show the HTML repr or trust the notebook.</b></div><div class=\"sk-container\" hidden><div class=\"sk-item sk-dashed-wrapped\"><div class='sk-label-container'><div class=\"sk-label sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=UUID('0e1c8034-cd45-4ebc-927a-e04784d72c6a') type=\"checkbox\" ><label for=UUID('0e1c8034-cd45-4ebc-927a-e04784d72c6a') class='sk-toggleable__label sk-toggleable__label-arrow'>ClassifierPipeline<a class=\"sk-estimator-doc-link\" rel=\"noreferrer\" target=\"_blank\" href=\"https://www.sktime.net/en/v0.35.0/api_reference/auto_generated/sktime.classification.compose.ClassifierPipeline.html\">?<span>Documentation for ClassifierPipeline</span></a></label><div class=\"sk-toggleable__content\"><pre>ClassifierPipeline(classifier=KNeighborsTimeSeriesClassifier(),\n",
       "                   transformers=[ExponentTransformer()])</pre></div></div></div><div class=\"sk-serial\"><div class='sk-item'><div class=\"sk-estimator sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=UUID('1611cc66-1245-4418-97f9-08aa3e674040') type=\"checkbox\" ><label for=UUID('1611cc66-1245-4418-97f9-08aa3e674040') class='sk-toggleable__label sk-toggleable__label-arrow'>ExponentTransformer<a class=\"sk-estimator-doc-link\" rel=\"noreferrer\" target=\"_blank\" href=\"https://www.sktime.net/en/v0.35.0/api_reference/auto_generated/sktime.transformations.series.exponent.ExponentTransformer.html\">?<span>Documentation for ExponentTransformer</span></a></label><div class=\"sk-toggleable__content\"><pre>ExponentTransformer()</pre></div></div></div><div class='sk-item'><div class=\"sk-estimator sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=UUID('01353b70-03ab-4b4c-95ff-c773fbedb286') type=\"checkbox\" ><label for=UUID('01353b70-03ab-4b4c-95ff-c773fbedb286') class='sk-toggleable__label sk-toggleable__label-arrow'>KNeighborsTimeSeriesClassifier<a class=\"sk-estimator-doc-link\" rel=\"noreferrer\" target=\"_blank\" href=\"https://www.sktime.net/en/v0.35.0/api_reference/auto_generated/sktime.classification.distance_based.KNeighborsTimeSeriesClassifier.html\">?<span>Documentation for KNeighborsTimeSeriesClassifier</span></a></label><div class=\"sk-toggleable__content\"><pre>KNeighborsTimeSeriesClassifier()</pre></div></div></div></div></div></div></div>"
      ],
      "text/plain": [
       "ClassifierPipeline(classifier=KNeighborsTimeSeriesClassifier(),\n",
       "                   transformers=[ExponentTransformer()])"
      ]
     },
     "execution_count": 43,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sktime.datasets import load_unit_test\n",
    "\n",
    "X_train, y_train = load_unit_test(split=\"TRAIN\")\n",
    "X_test, _ = load_unit_test(split=\"TEST\")\n",
    "\n",
    "# this is a ClassifierPipeline with the same interface as knn-classifier\n",
    "# first applies exponent transform, then knn-classifier\n",
    "pipe.fit(X_train, y_train)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`sktime` transformers pipeline with `sklearn` classifiers!\n",
    "\n",
    "This allows to build \"time series feature extraction then `sklearn` classify`\" pipelines:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<style>#sk-40340dd5-d83c-477f-9ae8-07a78ff0afc6 {\n",
       "    /* Definition of color scheme common for light and dark mode */\n",
       "    --sklearn-color-text: black;\n",
       "    --sklearn-color-line: gray;\n",
       "    /* Definition of color scheme for objects */\n",
       "    --sklearn-color-level-0: #fff5e6;\n",
       "    --sklearn-color-level-1: #f6e4d2;\n",
       "    --sklearn-color-level-2: #ffe0b3;\n",
       "    --sklearn-color-level-3: chocolate;\n",
       "\n",
       "    /* Specific color for light theme */\n",
       "    --sklearn-color-text-on-default-background: var(--theme-code-foreground, var(--jp-content-font-color1, black));\n",
       "    --sklearn-color-background: var(--theme-background, var(--jp-layout-color0, white));\n",
       "    --sklearn-color-border-box: var(--theme-code-foreground, var(--jp-content-font-color1, black));\n",
       "    --sklearn-color-icon: #696969;\n",
       "\n",
       "    @media (prefers-color-scheme: dark) {\n",
       "      /* Redefinition of color scheme for dark theme */\n",
       "      --sklearn-color-text-on-default-background: var(--theme-code-foreground, var(--jp-content-font-color1, white));\n",
       "      --sklearn-color-background: var(--theme-background, var(--jp-layout-color0, #111));\n",
       "      --sklearn-color-border-box: var(--theme-code-foreground, var(--jp-content-font-color1, white));\n",
       "      --sklearn-color-icon: #878787;\n",
       "    }\n",
       "  }\n",
       "\n",
       "  #sk-40340dd5-d83c-477f-9ae8-07a78ff0afc6 {\n",
       "    color: var(--sklearn-color-text);\n",
       "  }\n",
       "\n",
       "  #sk-40340dd5-d83c-477f-9ae8-07a78ff0afc6 pre {\n",
       "    padding: 0;\n",
       "  }\n",
       "\n",
       "  #sk-40340dd5-d83c-477f-9ae8-07a78ff0afc6 input.sk-hidden--visually {\n",
       "    border: 0;\n",
       "    clip: rect(1px 1px 1px 1px);\n",
       "    clip: rect(1px, 1px, 1px, 1px);\n",
       "    height: 1px;\n",
       "    margin: -1px;\n",
       "    overflow: hidden;\n",
       "    padding: 0;\n",
       "    position: absolute;\n",
       "    width: 1px;\n",
       "  }\n",
       "\n",
       "  #sk-40340dd5-d83c-477f-9ae8-07a78ff0afc6 div.sk-dashed-wrapped {\n",
       "    border: 1px dashed var(--sklearn-color-line);\n",
       "    margin: 0 0.4em 0.5em 0.4em;\n",
       "    box-sizing: border-box;\n",
       "    padding-bottom: 0.4em;\n",
       "    background-color: var(--sklearn-color-background);\n",
       "  }\n",
       "\n",
       "  #sk-40340dd5-d83c-477f-9ae8-07a78ff0afc6 div.sk-container {\n",
       "    /* jupyter's `normalize.less` sets `[hidden] { display: none; }`\n",
       "       but bootstrap.min.css set `[hidden] { display: none !important; }`\n",
       "       so we also need the `!important` here to be able to override the\n",
       "       default hidden behavior on the sphinx rendered scikit-learn.org.\n",
       "       See: https://github.com/scikit-learn/scikit-learn/issues/21755 */\n",
       "    display: inline-block !important;\n",
       "    position: relative;\n",
       "  }\n",
       "\n",
       "  #sk-40340dd5-d83c-477f-9ae8-07a78ff0afc6 div.sk-text-repr-fallback {\n",
       "    display: none;\n",
       "  }\n",
       "\n",
       "  div.sk-parallel-item,\n",
       "  div.sk-serial,\n",
       "  div.sk-item {\n",
       "    /* draw centered vertical line to link estimators */\n",
       "    background-image: linear-gradient(var(--sklearn-color-text-on-default-background), var(--sklearn-color-text-on-default-background));\n",
       "    background-size: 2px 100%;\n",
       "    background-repeat: no-repeat;\n",
       "    background-position: center center;\n",
       "  }\n",
       "\n",
       "  /* Parallel-specific style estimator block */\n",
       "\n",
       "  #sk-40340dd5-d83c-477f-9ae8-07a78ff0afc6 div.sk-parallel-item::after {\n",
       "    content: \"\";\n",
       "    width: 100%;\n",
       "    border-bottom: 2px solid var(--sklearn-color-text-on-default-background);\n",
       "    flex-grow: 1;\n",
       "  }\n",
       "\n",
       "  #sk-40340dd5-d83c-477f-9ae8-07a78ff0afc6 div.sk-parallel {\n",
       "    display: flex;\n",
       "    align-items: stretch;\n",
       "    justify-content: center;\n",
       "    background-color: var(--sklearn-color-background);\n",
       "    position: relative;\n",
       "  }\n",
       "\n",
       "  #sk-40340dd5-d83c-477f-9ae8-07a78ff0afc6 div.sk-parallel-item {\n",
       "    display: flex;\n",
       "    flex-direction: column;\n",
       "  }\n",
       "\n",
       "  #sk-40340dd5-d83c-477f-9ae8-07a78ff0afc6 div.sk-parallel-item:first-child::after {\n",
       "    align-self: flex-end;\n",
       "    width: 50%;\n",
       "  }\n",
       "\n",
       "  #sk-40340dd5-d83c-477f-9ae8-07a78ff0afc6 div.sk-parallel-item:last-child::after {\n",
       "    align-self: flex-start;\n",
       "    width: 50%;\n",
       "  }\n",
       "\n",
       "  #sk-40340dd5-d83c-477f-9ae8-07a78ff0afc6 div.sk-parallel-item:only-child::after {\n",
       "    width: 0;\n",
       "  }\n",
       "\n",
       "  /* Serial-specific style estimator block */\n",
       "\n",
       "  #sk-40340dd5-d83c-477f-9ae8-07a78ff0afc6 div.sk-serial {\n",
       "    display: flex;\n",
       "    flex-direction: column;\n",
       "    align-items: center;\n",
       "    background-color: var(--sklearn-color-background);\n",
       "    padding-right: 1em;\n",
       "    padding-left: 1em;\n",
       "  }\n",
       "\n",
       "\n",
       "  /* Toggleable style: style used for estimator/Pipeline/ColumnTransformer box that is\n",
       "  clickable and can be expanded/collapsed.\n",
       "  - Pipeline and ColumnTransformer use this feature and define the default style\n",
       "  - Estimators will overwrite some part of the style using the `sk-estimator` class\n",
       "  */\n",
       "\n",
       "  /* Pipeline and ColumnTransformer style (default) */\n",
       "\n",
       "  #sk-40340dd5-d83c-477f-9ae8-07a78ff0afc6 div.sk-toggleable {\n",
       "    /* Default theme specific background. It is overwritten whether we have a\n",
       "    specific estimator or a Pipeline/ColumnTransformer */\n",
       "    background-color: var(--sklearn-color-background);\n",
       "  }\n",
       "\n",
       "  /* Toggleable label */\n",
       "  #sk-40340dd5-d83c-477f-9ae8-07a78ff0afc6 label.sk-toggleable__label {\n",
       "    cursor: pointer;\n",
       "    display: block;\n",
       "    width: 100%;\n",
       "    margin-bottom: 0;\n",
       "    padding: 0.5em;\n",
       "    box-sizing: border-box;\n",
       "    text-align: center;\n",
       "  }\n",
       "\n",
       "  #sk-40340dd5-d83c-477f-9ae8-07a78ff0afc6 label.sk-toggleable__label-arrow:before {\n",
       "    /* Arrow on the left of the label */\n",
       "    content: \"▸\";\n",
       "    float: left;\n",
       "    margin-right: 0.25em;\n",
       "    color: var(--sklearn-color-icon);\n",
       "  }\n",
       "\n",
       "  #sk-40340dd5-d83c-477f-9ae8-07a78ff0afc6 label.sk-toggleable__label-arrow:hover:before {\n",
       "    color: var(--sklearn-color-text);\n",
       "  }\n",
       "\n",
       "  /* Toggleable content - dropdown */\n",
       "\n",
       "  #sk-40340dd5-d83c-477f-9ae8-07a78ff0afc6 div.sk-toggleable__content {\n",
       "    max-height: 0;\n",
       "    max-width: 0;\n",
       "    overflow: hidden;\n",
       "    text-align: left;\n",
       "    background-color: var(--sklearn-color-level-0);\n",
       "  }\n",
       "\n",
       "  #sk-40340dd5-d83c-477f-9ae8-07a78ff0afc6 div.sk-toggleable__content pre {\n",
       "    margin: 0.2em;\n",
       "    border-radius: 0.25em;\n",
       "    color: var(--sklearn-color-text);\n",
       "    background-color: var(--sklearn-color-level-0);\n",
       "  }\n",
       "\n",
       "  #sk-40340dd5-d83c-477f-9ae8-07a78ff0afc6 input.sk-toggleable__control:checked~div.sk-toggleable__content {\n",
       "    /* Expand drop-down */\n",
       "    max-height: 200px;\n",
       "    max-width: 100%;\n",
       "    overflow: auto;\n",
       "  }\n",
       "\n",
       "  #sk-40340dd5-d83c-477f-9ae8-07a78ff0afc6 input.sk-toggleable__control:checked~label.sk-toggleable__label-arrow:before {\n",
       "    content: \"▾\";\n",
       "  }\n",
       "\n",
       "  /* Pipeline/ColumnTransformer-specific style */\n",
       "\n",
       "  #sk-40340dd5-d83c-477f-9ae8-07a78ff0afc6 div.sk-label input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
       "    color: var(--sklearn-color-text);\n",
       "    background-color: var(--sklearn-color-level-2);\n",
       "  }\n",
       "\n",
       "  /* Estimator-specific style */\n",
       "\n",
       "  /* Colorize estimator box */\n",
       "  #sk-40340dd5-d83c-477f-9ae8-07a78ff0afc6 div.sk-estimator input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
       "    /* unfitted */\n",
       "    background-color: var(--sklearn-color-level-2);\n",
       "  }\n",
       "\n",
       "  #sk-40340dd5-d83c-477f-9ae8-07a78ff0afc6 div.sk-label label.sk-toggleable__label,\n",
       "  #sk-40340dd5-d83c-477f-9ae8-07a78ff0afc6 div.sk-label label {\n",
       "    /* The background is the default theme color */\n",
       "    color: var(--sklearn-color-text-on-default-background);\n",
       "  }\n",
       "\n",
       "  /* On hover, darken the color of the background */\n",
       "  #sk-40340dd5-d83c-477f-9ae8-07a78ff0afc6 div.sk-label:hover label.sk-toggleable__label {\n",
       "    color: var(--sklearn-color-text);\n",
       "    background-color: var(--sklearn-color-level-2);\n",
       "  }\n",
       "\n",
       "  /* Estimator label */\n",
       "\n",
       "  #sk-40340dd5-d83c-477f-9ae8-07a78ff0afc6 div.sk-label label {\n",
       "    font-family: monospace;\n",
       "    font-weight: bold;\n",
       "    display: inline-block;\n",
       "    line-height: 1.2em;\n",
       "  }\n",
       "\n",
       "  #sk-40340dd5-d83c-477f-9ae8-07a78ff0afc6 div.sk-label-container {\n",
       "    text-align: center;\n",
       "  }\n",
       "\n",
       "  /* Estimator-specific */\n",
       "  #sk-40340dd5-d83c-477f-9ae8-07a78ff0afc6 div.sk-estimator {\n",
       "    font-family: monospace;\n",
       "    border: 1px dotted var(--sklearn-color-border-box);\n",
       "    border-radius: 0.25em;\n",
       "    box-sizing: border-box;\n",
       "    margin-bottom: 0.5em;\n",
       "    background-color: var(--sklearn-color-level-0);\n",
       "  }\n",
       "\n",
       "  /* on hover */\n",
       "  #sk-40340dd5-d83c-477f-9ae8-07a78ff0afc6 div.sk-estimator:hover {\n",
       "    background-color: var(--sklearn-color-level-2);\n",
       "  }\n",
       "\n",
       "  /* Specification for estimator info */\n",
       "\n",
       "  .sk-estimator-doc-link,\n",
       "  a:link.sk-estimator-doc-link,\n",
       "  a:visited.sk-estimator-doc-link {\n",
       "    float: right;\n",
       "    font-size: smaller;\n",
       "    line-height: 1em;\n",
       "    font-family: monospace;\n",
       "    background-color: var(--sklearn-color-background);\n",
       "    border-radius: 1em;\n",
       "    height: 1em;\n",
       "    width: 1em;\n",
       "    text-decoration: none !important;\n",
       "    margin-left: 1ex;\n",
       "    border: var(--sklearn-color-level-1) 1pt solid;\n",
       "    color: var(--sklearn-color-level-1);\n",
       "  }\n",
       "\n",
       "  /* On hover */\n",
       "  div.sk-estimator:hover .sk-estimator-doc-link:hover,\n",
       "  .sk-estimator-doc-link:hover,\n",
       "  div.sk-label-container:hover .sk-estimator-doc-link:hover,\n",
       "  .sk-estimator-doc-link:hover {\n",
       "    background-color: var(--sklearn-color-level-3);\n",
       "    color: var(--sklearn-color-background);\n",
       "    text-decoration: none;\n",
       "  }\n",
       "\n",
       "  /* Span, style for the box shown on hovering the info icon */\n",
       "  .sk-estimator-doc-link span {\n",
       "    display: none;\n",
       "    z-index: 9999;\n",
       "    position: relative;\n",
       "    font-weight: normal;\n",
       "    right: .2ex;\n",
       "    padding: .5ex;\n",
       "    margin: .5ex;\n",
       "    width: min-content;\n",
       "    min-width: 20ex;\n",
       "    max-width: 50ex;\n",
       "    color: var(--sklearn-color-text);\n",
       "    box-shadow: 2pt 2pt 4pt #999;\n",
       "    background: var(--sklearn-color-level-0);\n",
       "    border: .5pt solid var(--sklearn-color-level-3);\n",
       "  }\n",
       "\n",
       "  .sk-estimator-doc-link:hover span {\n",
       "    display: block;\n",
       "  }\n",
       "\n",
       "  /* \"?\"-specific style due to the `<a>` HTML tag */\n",
       "\n",
       "  #sk-40340dd5-d83c-477f-9ae8-07a78ff0afc6 a.estimator_doc_link {\n",
       "    float: right;\n",
       "    font-size: 1rem;\n",
       "    line-height: 1em;\n",
       "    font-family: monospace;\n",
       "    background-color: var(--sklearn-color-background);\n",
       "    border-radius: 1rem;\n",
       "    height: 1rem;\n",
       "    width: 1rem;\n",
       "    text-decoration: none;\n",
       "    color: var(--sklearn-color-level-1);\n",
       "    border: var(--sklearn-color-level-1) 1pt solid;\n",
       "  }\n",
       "\n",
       "  /* On hover */\n",
       "  #sk-40340dd5-d83c-477f-9ae8-07a78ff0afc6 a.estimator_doc_link:hover {\n",
       "    background-color: var(--sklearn-color-level-3);\n",
       "    color: var(--sklearn-color-background);\n",
       "    text-decoration: none;\n",
       "  }\n",
       "</style><div id='sk-40340dd5-d83c-477f-9ae8-07a78ff0afc6' class=\"sk-top-container\"><div class=\"sk-text-repr-fallback\"><pre>SklearnClassifierPipeline(classifier=RandomForestClassifier(),\n",
       "                          transformers=[SummaryTransformer()])</pre><b>Please rerun this cell to show the HTML repr or trust the notebook.</b></div><div class=\"sk-container\" hidden><div class=\"sk-item sk-dashed-wrapped\"><div class='sk-label-container'><div class=\"sk-label sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=UUID('83a44671-32e6-4032-8b11-10d4933ff9f8') type=\"checkbox\" ><label for=UUID('83a44671-32e6-4032-8b11-10d4933ff9f8') class='sk-toggleable__label sk-toggleable__label-arrow'>SklearnClassifierPipeline<a class=\"sk-estimator-doc-link\" rel=\"noreferrer\" target=\"_blank\" href=\"https://www.sktime.net/en/v0.35.0/api_reference/auto_generated/sktime.classification.compose.SklearnClassifierPipeline.html\">?<span>Documentation for SklearnClassifierPipeline</span></a></label><div class=\"sk-toggleable__content\"><pre>SklearnClassifierPipeline(classifier=RandomForestClassifier(),\n",
       "                          transformers=[SummaryTransformer()])</pre></div></div></div><div class=\"sk-serial\"><div class='sk-item'><div class=\"sk-estimator sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=UUID('1b12e59e-9808-49bc-b79d-df948dea6882') type=\"checkbox\" ><label for=UUID('1b12e59e-9808-49bc-b79d-df948dea6882') class='sk-toggleable__label sk-toggleable__label-arrow'>SummaryTransformer<a class=\"sk-estimator-doc-link\" rel=\"noreferrer\" target=\"_blank\" href=\"https://www.sktime.net/en/v0.35.0/api_reference/auto_generated/sktime.transformations.series.summarize.SummaryTransformer.html\">?<span>Documentation for SummaryTransformer</span></a></label><div class=\"sk-toggleable__content\"><pre>SummaryTransformer()</pre></div></div></div><div class='sk-item'><div class=\"sk-estimator sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=UUID('7d36f4f0-6dba-49b2-9d49-f52a9481e4e3') type=\"checkbox\" ><label for=UUID('7d36f4f0-6dba-49b2-9d49-f52a9481e4e3') class='sk-toggleable__label sk-toggleable__label-arrow'>RandomForestClassifier<a class=\"sk-estimator-doc-link\" rel=\"noreferrer\" target=\"_blank\" href=\"https://scikit-learn.org/1.5/modules/generated/sklearn.ensemble.RandomForestClassifier.html\">?<span>Documentation for RandomForestClassifier</span></a></label><div class=\"sk-toggleable__content\"><pre>RandomForestClassifier()</pre></div></div></div></div></div></div></div>"
      ],
      "text/plain": [
       "SklearnClassifierPipeline(classifier=RandomForestClassifier(),\n",
       "                          transformers=[SummaryTransformer()])"
      ]
     },
     "execution_count": 44,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sklearn.ensemble import RandomForestClassifier\n",
    "\n",
    "from sktime.transformations.series.summarize import SummaryTransformer\n",
    "\n",
    "# specify summary transformer\n",
    "summary_rf = SummaryTransformer() * RandomForestClassifier()\n",
    "\n",
    "summary_rf.fit(X_train, y_train)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.4.3 Using transformers to deal with unequal length or missing values"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "pro tip: useful transformers to pipeline are those that \"improve\" capabilities!\n",
    "\n",
    "Search for these transformer tags:\n",
    "\n",
    "* `\"capability:unequal_length:removes\"` - ensures all instances in the panel have equal length afterwards. Examples: padding, cutting, resampling.\n",
    "* `\"capability:missing_values:removes\"` - removes all missing values from the data (e.g., series, panel) passed to it. Example: mean imputation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>name</th>\n",
       "      <th>object</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>ClearSky</td>\n",
       "      <td>&lt;class 'sktime.transformations.series.clear_sk...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>IntervalSegmenter</td>\n",
       "      <td>&lt;class 'sktime.transformations.panel.segment.I...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>PaddingTransformer</td>\n",
       "      <td>&lt;class 'sktime.transformations.panel.padder.Pa...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>RandomIntervalSegmenter</td>\n",
       "      <td>&lt;class 'sktime.transformations.panel.segment.R...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>SlopeTransformer</td>\n",
       "      <td>&lt;class 'sktime.transformations.panel.slope.Slo...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>SubsequenceExtractionTransformer</td>\n",
       "      <td>&lt;class 'sktime.transformations.series.subseque...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>TimeBinAggregate</td>\n",
       "      <td>&lt;class 'sktime.transformations.series.binning....</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>TruncationTransformer</td>\n",
       "      <td>&lt;class 'sktime.transformations.panel.truncatio...</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                               name                                             object\n",
       "0                          ClearSky  <class 'sktime.transformations.series.clear_sk...\n",
       "1                 IntervalSegmenter  <class 'sktime.transformations.panel.segment.I...\n",
       "2                PaddingTransformer  <class 'sktime.transformations.panel.padder.Pa...\n",
       "3           RandomIntervalSegmenter  <class 'sktime.transformations.panel.segment.R...\n",
       "4                  SlopeTransformer  <class 'sktime.transformations.panel.slope.Slo...\n",
       "5  SubsequenceExtractionTransformer  <class 'sktime.transformations.series.subseque...\n",
       "6                  TimeBinAggregate  <class 'sktime.transformations.series.binning....\n",
       "7             TruncationTransformer  <class 'sktime.transformations.panel.truncatio..."
      ]
     },
     "execution_count": 45,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# all transformers that guarantee that the output is equal length and equal index\n",
    "from sktime.registry import all_estimators\n",
    "\n",
    "all_estimators(\n",
    "    \"transformer\",\n",
    "    as_dataframe=True,\n",
    "    filter_tags={\"capability:unequal_length:removes\": True},\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>name</th>\n",
       "      <th>object</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>ClearSky</td>\n",
       "      <td>&lt;class 'sktime.transformations.series.clear_sk...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>ClustererAsTransformer</td>\n",
       "      <td>&lt;class 'sktime.clustering.compose._as_transfor...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>DetectorAsTransformer</td>\n",
       "      <td>&lt;class 'sktime.detection.compose._as_transform...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>Imputer</td>\n",
       "      <td>&lt;class 'sktime.transformations.series.impute.I...</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                     name                                             object\n",
       "0                ClearSky  <class 'sktime.transformations.series.clear_sk...\n",
       "1  ClustererAsTransformer  <class 'sktime.clustering.compose._as_transfor...\n",
       "2   DetectorAsTransformer  <class 'sktime.detection.compose._as_transform...\n",
       "3                 Imputer  <class 'sktime.transformations.series.impute.I..."
      ]
     },
     "execution_count": 46,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# all transformers that guarantee the output has no missing values\n",
    "from sktime.registry import all_estimators\n",
    "\n",
    "all_estimators(\n",
    "    \"transformer\",\n",
    "    as_dataframe=True,\n",
    "    filter_tags={\"capability:missing_values:removes\": True},\n",
    ")"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "minor note:\n",
    "\n",
    "some transformers guarantee \"no missing values\" under some conditions but not always, e.g., `TimeBinAggregate`"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "let's check the tags in one example"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'python_version': None,\n",
       " 'python_dependencies': None,\n",
       " 'env_marker': None,\n",
       " 'sktime_version': '0.35.0',\n",
       " 'object_type': 'classifier',\n",
       " 'X_inner_mtype': 'numpy3D',\n",
       " 'y_inner_mtype': 'numpy1D',\n",
       " 'capability:multioutput': False,\n",
       " 'capability:multivariate': True,\n",
       " 'capability:unequal_length': False,\n",
       " 'capability:missing_values': False,\n",
       " 'capability:train_estimate': False,\n",
       " 'capability:feature_importance': False,\n",
       " 'capability:contractable': False,\n",
       " 'capability:multithreading': True,\n",
       " 'capability:predict_proba': True,\n",
       " 'requires_cython': False,\n",
       " 'authors': ['MatthewMiddlehurst'],\n",
       " 'maintainers': 'sktime developers',\n",
       " 'classifier_type': 'feature'}"
      ]
     },
     "execution_count": 47,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# list all classifiers in sktime\n",
    "from sktime.classification.feature_based import SummaryClassifier\n",
    "\n",
    "no_missing_clf = SummaryClassifier()\n",
    "\n",
    "no_missing_clf.get_tags()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'python_version': None,\n",
       " 'python_dependencies': None,\n",
       " 'env_marker': None,\n",
       " 'sktime_version': '0.35.0',\n",
       " 'object_type': 'classifier',\n",
       " 'X_inner_mtype': 'pd-multiindex',\n",
       " 'y_inner_mtype': 'numpy1D',\n",
       " 'capability:multioutput': False,\n",
       " 'capability:multivariate': True,\n",
       " 'capability:unequal_length': False,\n",
       " 'capability:missing_values': True,\n",
       " 'capability:train_estimate': False,\n",
       " 'capability:feature_importance': False,\n",
       " 'capability:contractable': False,\n",
       " 'capability:multithreading': False,\n",
       " 'capability:predict_proba': True,\n",
       " 'requires_cython': False,\n",
       " 'authors': ['fkiraly'],\n",
       " 'maintainers': 'sktime developers',\n",
       " 'visual_block_kind': 'serial'}"
      ]
     },
     "execution_count": 48,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sktime.transformations.series.impute import Imputer\n",
    "\n",
    "clf_can_do_missing = Imputer() * SummaryClassifier()\n",
    "\n",
    "clf_can_do_missing.get_tags()"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.4.4 Tuning and model selection"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`sktime` classifiers are compatible with `sklearn` model selection and composition tools using `sktime` data formats.\n",
    "\n",
    "This extends to grid tuning and cross-validation, as long as `numpy` based formats or length/instance indexed formats are used."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sktime.datasets import load_unit_test\n",
    "\n",
    "X_train, y_train = load_unit_test(split=\"TRAIN\")\n",
    "X_test, _ = load_unit_test(split=\"TEST\")"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Cross-validation using the `sklearn` `cross_val_score` and `KFold` functionality:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0.2, 0.8, 0.6, 0.8])"
      ]
     },
     "execution_count": 50,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sklearn.model_selection import KFold, cross_val_score\n",
    "\n",
    "from sktime.classification.feature_based import SummaryClassifier\n",
    "\n",
    "clf = SummaryClassifier()\n",
    "\n",
    "cross_val_score(clf, X_train, y=y_train, cv=KFold(n_splits=4))"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Parameter tuning using `sklearn` `GridSearchCV`, we tune the _k_ and distance measure for a K-NN classifier:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.model_selection import GridSearchCV\n",
    "\n",
    "from sktime.classification.distance_based import KNeighborsTimeSeriesClassifier\n",
    "\n",
    "knn = KNeighborsTimeSeriesClassifier()\n",
    "param_grid = {\"n_neighbors\": [1, 5], \"distance\": [\"euclidean\", \"dtw\"]}\n",
    "parameter_tuning_method = GridSearchCV(knn, param_grid, cv=KFold(n_splits=4))\n",
    "\n",
    "parameter_tuning_method.fit(X_train, y_train)\n",
    "y_pred = parameter_tuning_method.predict(X_test)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.4.5 Advanced Composition cheat sheet - AutoML, bagging, ensembles"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* common ensembling patterns: `BaggingClassifier`, `WeightedEnsembleClassifier`\n",
    "* composability with `sklearn` classifier, regressor building blocks still applies\n",
    "* AutoML can be achieved by combining tuning with `MultiplexClassifier` or `MultiplexTransformer`"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "pro tip: bagging with a fixed single column subset can be used to turn an univariate classifier into a multivariate classifier!"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2.5 Appendix - Extension guide"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`sktime` is meant to be easily extensible, for direct contribution to `sktime` as well as for local/private extension with custom methods.\n",
    "\n",
    "To extend `sktime` with a new local or contributed estimator, a good workflow to follow is:\n",
    "\n",
    "0. find the right extension template for the type of estimator you want to add - e.g., classifier, regressor, clusterer, etc. The extension templates are located in the [`extension_templates](https://github.com/sktime/sktime/blob/main/extension_templates) directory\n",
    "1. read through the extension template - this is a `python` file with `todo` blocks that mark the places in which changes need to be added.\n",
    "2. optionally, if you are planning any major surgeries to the interface: look at the base class - note that \"ordinary\" extension (e.g., new algorithm) should be easily doable without this.\n",
    "3. copy the extension template to a local folder in your own repository (local/private extension), or to a suitable location in your clone of the `sktime` or affiliated repository (if contributed extension), inside `sktime.[name_of_task]`; rename the file and update the file docstring appropriately.\n",
    "4. address the \"todo\" parts. Usually, this means: changing the name of the class, setting the tag values, specifying hyper-parameters, filling in `__init__`, `_fit`, `_predict` and/or other methods (for details see the extension template). You can add private methods as long as they do not override the default public interface. For more details, see the extension template.\n",
    "5. to test your estimator manually: import your estimator and run it in the basic vignettes above.\n",
    "6. to test your estimator automatically: call `sktime.tests.test_all_estimators.check_estimator` on your estimator. You can call this on a class or object instance. Ensure you have specified test parameters in the `get_test_params` method, according to the extension template.\n",
    "\n",
    "In case of direct contribution to `sktime` or one of its affiliated packages, additionally:\n",
    "* Add yourself as an author and/or a maintainer for the new estimator file(s), via `\"authors\"` and `\"maintainers\"` tag.\n",
    "* create a pull request that contains only the new estimators (and their inheritance tree, if it's not just one class), as well as the automated tests as described above.\n",
    "* in the pull request, describe the estimator and optimally provide a publication or other technical reference for the strategy it implements.\n",
    "* before making the pull request, ensure that you have all necessary permissions to contribute the code to a permissive license (BSD-3) open source project."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "sktime-skpro-skbase-311",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
